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

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

using CommonMP.HYSSOP.CoreImpl.HSData;
using CommonMP.HYSSOP.CoreImpl.HSTools;

using CommonMP.HYMCO.Interface.Model;
using CommonMP.HYMCO.Interface.Data;
using CommonMP.HYMCO.CoreImpl.Data;
using CommonMP.HYMCO.CoreImpl.Tool;

// ToDo namespace は　モデル開発者が変更して、ユニークな名称にして下さい
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>
    /// <para>remarks:</para>
    /// <para>
    /// ニューラルネットワーク処理を組み込むサンプルのため、
    /// 計算処理の中断／再開には対応していない</para>
    /// </remarks>
    public class NeuralNetworkModel : McForecastModelBase
    {
        /// <summary> 演算データ（キャスト用） </summary>
        NeuralNetworkCalInfo m_csMyInf = null;   // 便利の為、キャスト用に定義しておく

        /// <summary>ニューラルネットワーク処理本体部</summary>
        NN_NeuralNetwork m_csNeuralNetwaork = null;

        /// <summary>学習結果セーブ </summary>
        HySString csWeightSaveFileName = new HySString("LearndResult.dat");

        //=========================
        // 演算実行前処理関連メソッド
        //=========================


        /// <summary><para>method outline:</para>
        /// <para>入力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReceiveConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>受信するデータが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = true;
            for (long lLp = 0; lLp < lInputDataNum; lLp++)
            {   // 入力する伝送データ数分繰り返します。
                if (NeuralNetworkSampleDefine.LEARN_INPUT_PATTERN_ID.Equals(csInputCellData[lLp].GetReceivePatternID()) == true)
                {   // 学習入力パターン
                    m_csMyInf.LEARN_INPUT_PATTERN_ID = lLp;
                }
                else if (NeuralNetworkSampleDefine.LEARN_TEACH_PATTERN_ID.Equals(csInputCellData[lLp].GetReceivePatternID()) == true)
                {   // 学習教師パターン
                    m_csMyInf.LEARN_TEACH_PATTERN_ID = lLp;
                }
                else if (NeuralNetworkSampleDefine.RECOG_INPUT_PATTERN_ID.Equals(csInputCellData[lLp].GetReceivePatternID()) == true)
                {   // 連想入力パターン
                    m_csMyInf.RECOG_INPUT_PATTERN_ID = lLp;
                }
                else 
                {
                    // エラー
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), NeuralNetworkSampleDefine.NEURALNET_MODEL_KIND,
                         Properties.Resources.STATEMENT_REC_PATTERN_NO_SET );
                   // csErrorInf.AddCheckErrorData(this.GetID(), NeuralNetworkSampleDefine.NEURALNET_MODEL_KIND,
                   //     "Receive Pattern is not set.");
                    bRtn = false;
                }
                // To Do
                // 入力する伝送データの型式や設定値等をチェックし、一つでも期待情報でなければ、bRtn=false; を設定します。
                // m_csInputData[lLp]

            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>出力側の接続情報チェック</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SendConnectionCheck(ref csErrorInf)</para>
        /// </example>
        /// <param name="csErrorInf">エラー出力</param>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>送信端子に設定されている伝送データが自モデルが期待している情報か否かをチェックする</para>
        /// </remarks>
        protected override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)
        {
            bool bRtn = true;
            for (long lLp = 0; lLp < lOutputDataNum; lLp++)
            {   // 出力する伝送データ数分繰り返します。

                if (NeuralNetworkSampleDefine.RECOG_OUTPUT_PATTERN_ID.Equals(csOutputCellData[lLp].GetSendPatternID()) == true)
                {   // 連想出力
                    m_csMyInf.RECOG_OUTPUT_PATTERN_ID = lLp;
                }
                else if (NeuralNetworkSampleDefine.LEARN_ERROR_OUT_PATTERN_ID.Equals(csOutputCellData[lLp].GetSendPatternID()) == true)
                {   // 学習誤差出力
                    m_csMyInf.LEARN_ERROR_OUT_PATTERN_ID = lLp;
                }
                else
                {
                    // エラー
                   // ver1.5 エラートレース日本語対応
                    csErrorInf.AddCheckErrorData(this.GetID(), NeuralNetworkSampleDefine.NEURALNET_MODEL_KIND,
                         Properties.Resources.STATEMENT_SND_PATTERN_NO_SET );
                   // csErrorInf.AddCheckErrorData(this.GetID(), NeuralNetworkSampleDefine.NEURALNET_MODEL_KIND,
                   //     "Send Pattern is not set.");
                    bRtn = false;
                }
                // To Do
                // 出力する伝送データの型式や設定値等をチェックし、一つでも期待情報でなければ、bRtn=false; を設定します。
                //m_csOutputData[lLp]

            }
            return bRtn;
        }


        /// <summary><para>method outline:</para>
        /// <para>モデルを初期化する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>Initialize(csInitialData)</para>
        /// </example>
        /// <param name="csInitialData">初期化設定情報</param>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override bool Initialize(ref McPropertyInfoRoot csInitialData, long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            bool bRtn = false;
            // 引数で与えられたデータを　キャストしています。
            McInitialInfo csInDt = csInitialData as McInitialInfo;

            if (csInDt != null)
            {
                bRtn = true;

                csInDt.GetInfo("m_lMode", ref m_csMyInf.m_lMode);
                // >> Ver1.0 → Ver1.1 により、モデル用データ格納場所を変更（プログラムによる相対パス化）
                string sLearnedResult = "";
                csInDt.GetInfo("m_csLearnedResultStockFile", ref sLearnedResult);
                m_csMyInf.m_csLearnedResultStockFile = this.GetProjectGroupDirectory().ToString() + "\\" + sLearnedResult;
                //csInDt.GetInfo("m_csLearnedResultStockFile", ref m_csMyInf.m_csLearnedResultStockFile);
                // Ver1.0 → Ver1.1 により、モデル用データ格納場所を変更（プログラムによる相対パス化） <<
                
                csWeightSaveFileName = new HySString(m_csMyInf.m_csLearnedResultStockFile);

                csInDt.GetInfo("m_iLearnPtnNum", ref m_csMyInf.m_iLearnPtnNum);
                csInDt.GetInfo("m_dE2Limit", ref m_csMyInf.m_dE2Limit);
                csInDt.GetInfo("m_dSlope", ref m_csMyInf.m_dSlope);
                NN_Neuron.m_dSlope = m_csMyInf.m_dSlope;
                csInDt.GetInfo("m_dAlpha", ref m_csMyInf.m_dAlpha);
                NN_Network.m_dAlpha = m_csMyInf.m_dAlpha;
                csInDt.GetInfo("m_dInertia", ref m_csMyInf.m_dInertia);
                NN_Network.m_dInertia = m_csMyInf.m_dInertia;
                csInDt.GetInfo("m_iMaxLearnNum", ref m_csMyInf.m_iMaxLearnNum);
                if (m_csMyInf.m_lMode == 0)
                {   // 学習モード
                    m_csMyInf.m_bLearnFlg = false;
                    
                    m_csNeuralNetwaork.WeightInitialize(0.2, -0.2);

                    m_csMyInf.m_csNetInf.m_dW01 = m_csNeuralNetwaork.GetLayerWeight(0);
                    m_csMyInf.m_csNetInf.m_dW12 = m_csNeuralNetwaork.GetLayerWeight(1);
                    if (m_csMyInf.m_csNetInf.m_lLayerNum >= 4)
                    {
                        m_csMyInf.m_csNetInf.m_dW23 = m_csNeuralNetwaork.GetLayerWeight(2);
                    }
                }
                else
                {   // 想起モード
                    //string csSaveFile = HySEnvInf.GetHomeDirectory().ToString() + "\\temp\\" + this.csWeightSaveFileName.ToString();
                    //HySFile csFile = new HySFile(csSaveFile);
                    HySFile csFile = new HySFile(csWeightSaveFileName);
                    csFile.Open(HySFile.OPEN_MODE.OPEN, HySFile.READ_WRITE_MODE.READ, HySFile.DIRECTORY_MODE.NOT_MK_DIR);
                    //m_csMyInf = csFile.DataRead() as NeuralNetworkCalInfo;
                    m_csMyInf.m_csNetInf = csFile.DataRead() as NeuralNetworkCalInfo.NeruralNetworkStructInf;
                    csFile.Close();

                    //m_csMyInf.m_lMode = 1; // 再設定
                    m_csNeuralNetwaork.SetLayerWeight(0, m_csMyInf.m_csNetInf.m_dW01);
                    m_csNeuralNetwaork.SetLayerWeight(1, m_csMyInf.m_csNetInf.m_dW12);
                    if (m_csMyInf.m_csNetInf.m_lLayerNum >= 4)
                    {
                        m_csNeuralNetwaork.SetLayerWeight(2, m_csMyInf.m_csNetInf.m_dW23);
                    }

                    if (m_csMyInf.LEARN_ERROR_OUT_PATTERN_ID >= 0)
                    {   // 学習誤差信号を送るデータが設定されている為クリアする
                        // 連想時には、それを使用しない。
                        m_OutputCellData[m_csMyInf.LEARN_ERROR_OUT_PATTERN_ID].GetTranInfo().ResetData();
                    }
                }

                // To Do
                // 演算データ等で初期化が必要な情報に対して、引数で与えられた初期化情報の内容を読み取って、設定します。
            }
            return bRtn;
        }

        //=======================
        // 演算実行処理関連メソッド
        //=======================

        /// <summary><para>method outline:</para>
        /// <para>モデル演算</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = Calculate(ref csInputCellData)</para>
        /// </example>
        /// <param name="lInputDataNum">入力情報数</param>
        /// <param name="csInputCellData">演算に必要な入力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long Calculate(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            HySCellData[] csInCell = null;
            HySCellData[] csOutCell = null;
            HySCellData[] csErrorCell = null;
            if (m_csMyInf.m_lMode == 0)
            {   // 学習モードならば
                m_csMyInf.m_bLearnFlg = false;
                csInCell = csInputCellData[m_csMyInf.LEARN_INPUT_PATTERN_ID].GetInterpolatedCellD1();
                csOutCell = csInputCellData[m_csMyInf.LEARN_TEACH_PATTERN_ID].GetInterpolatedCellD1();

                double dErr = 0.0;
                for (int i = 0; i < m_csMyInf.m_iMaxLearnNum; i++)
                {
                    dErr = 0.0;
                    for (int iPtn = 0; iPtn < m_csMyInf.m_iLearnPtnNum; iPtn++)
                    {   // 学習パターン
                        for (int ll = 0; ll < m_csMyInf.m_csNetInf.m_iNeuronNumber[0]; ll++)
                        {
                            m_csMyInf.dInputData[ll] = csInCell[ll].m_dData[iPtn];
                        }
                        for (int ll = 0; ll < m_csMyInf.m_csNetInf.m_iNeuronNumber[m_csMyInf.m_csNetInf.m_lLayerNum - 1]; ll++)
                        {
                            m_csMyInf.dTchPtn[ll] = csOutCell[ll].m_dData[iPtn];
                        } 
                        dErr += m_csNeuralNetwaork.Learn(m_csMyInf.dInputData, m_csMyInf.dTchPtn);
                    }
                    dErr = dErr / (double)(m_csMyInf.m_iLearnPtnNum);
                    //
                    if (m_csMyInf.LEARN_ERROR_OUT_PATTERN_ID >= 0)
                    {   // 学習誤差信号を送る
                        if (i % 50 == 0 || dErr < m_csMyInf.m_dE2Limit)
                        {   // 毎回誤差信号を送るとオーバーフローのおそれがあるため間引いて送る
                            m_OutputCellData[m_csMyInf.LEARN_ERROR_OUT_PATTERN_ID].SetCurrentTime(m_csMyInf.m_csLearningTime.SetTime(m_csMyInf.m_csLearningTime.GetTime() + (double)i));
                            csErrorCell = m_OutputCellData[m_csMyInf.LEARN_ERROR_OUT_PATTERN_ID].PrepareSendCellD1();
                            csErrorCell[0].m_dData[0] = dErr*100.0;
                            m_OutputCellData[m_csMyInf.LEARN_ERROR_OUT_PATTERN_ID].SendData();
                        }
                    }
                    //
                    if (dErr < m_csMyInf.m_dE2Limit)
                    {
                        m_csMyInf.m_bLearnFlg = true;
                       // ver1.5 エラートレース日本語対応
                        String msg = Properties.Resources.STATEMENT_LEARNING_COMPLET + "(" + Properties.Resources.STATEMENT_LEARNING_NUMBER
                                       + i.ToString() + "),(" + Properties.Resources.STATEMENT_LEARNING_ERR + dErr.ToString() + ")";
                       // String msg = "学習完了：(学習回数=" + i.ToString() + "),(学習誤差=" + dErr.ToString() + ")";
                        McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "Calculate", msg);

                        // 学習結果の一時保管
                        //string csSaveFile = HySEnvInf.GetHomeDirectory().ToString() + "\\temp\\" + this.csWeightSaveFileName.ToString();
                        //HySFile csFile = new HySFile(csSaveFile);
                        HySFile csFile = new HySFile(csWeightSaveFileName);
                        csFile.Open(HySFile.OPEN_MODE.CREATE, HySFile.READ_WRITE_MODE.WRITE, HySFile.DIRECTORY_MODE.NOT_MK_DIR);
                        //csFile.DataWrite(m_csMyInf);
                        csFile.DataWrite(m_csMyInf.m_csNetInf);
                        csFile.Close();

                        // 強制終了させる為時刻を進めておく
                        this.m_csSimTime.SetTime(m_csSimTime.GetTime() + 3600.0 * 24.0 * 366.0 * 100.0);
                        this.m_csDltTime.SetTime(3600.0 * 24.0 * 366.0 * 100.0);
                        // 強制終了させる為時刻を進めておく
                        break;
                    } 
                }
                if (dErr >= m_csMyInf.m_dE2Limit)
                {
                   // ver1.5 エラートレース日本語対応
                    String msg = Properties.Resources.STATEMENT_LEARNING_CONVERG_NO + "(" + Properties.Resources.STATEMENT_LEARNING_NUMBER
                                  + m_csMyInf.m_iMaxLearnNum.ToString() + "),(" + Properties.Resources.STATEMENT_LEARNING_ERR + dErr.ToString() + ")";
                   // String msg = "学習収束せず：(学習回数=" + m_csMyInf.m_iMaxLearnNum.ToString() + "),(学習誤差=" + dErr.ToString() + ")";
                    McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "Calculate", msg);
                }
            }
            else
            {   // 連想モードならば
                csInCell = csInputCellData[m_csMyInf.LEARN_INPUT_PATTERN_ID].GetInterpolatedCellD1();
                //csOutCell = csInputCellData[m_csMyInf.LEARN_TEACH_PATTERN_ID].GetInterpolatedCellD1();
                if (m_csMyInf.RECOG_OUTPUT_PATTERN_ID >= 0)
                {   // 接続線があれば送信情報を設定
                    m_OutputCellData[m_csMyInf.RECOG_OUTPUT_PATTERN_ID].SetCurrentTime(this.m_csSimTime);
                    csOutCell = m_OutputCellData[m_csMyInf.RECOG_OUTPUT_PATTERN_ID].PrepareSendCellD1();
                }

                for (int iPtn = 0; iPtn < m_csMyInf.m_iLearnPtnNum; iPtn++)
                {   // 連想パターン
                   // ver1.5 エラートレース日本語対応
                    String msg = Properties.Resources.STATEMENT_ASSOCIAT_INPUT + "(" + iPtn.ToString() + ") = ";
                   // String msg = "連想入力ﾊﾟﾀｰﾝ(" + iPtn.ToString() + ") = ";
                    for (int ll = 0; ll < m_csMyInf.m_csNetInf.m_iNeuronNumber[0]; ll++)
                    {
                        m_csMyInf.dInputData[ll] = csInCell[ll].m_dData[iPtn];
                        msg += "[" +((int)(csInCell[ll].m_dData[iPtn]+0.0001)).ToString() + "]";
                    }
                    McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "Calculate", msg);

                    for (int ll = 0; ll < m_csMyInf.m_csNetInf.m_iNeuronNumber[m_csMyInf.m_csNetInf.m_lLayerNum - 1]; ll++)
                    {
                        m_csMyInf.dOnputData[ll] = 0.0;
                    }


                    // NN想起
                    m_csNeuralNetwaork.Recognize(m_csMyInf.dInputData, ref m_csMyInf.dOnputData);
                   // ver1.5 エラートレース日本語対応
                    msg = Properties.Resources.STATEMENT_ASSOCIAT_RESULT ;
                   // msg = "　          ＝＝＞連想結果 = ";
                    for (int ll = 0; ll < m_csMyInf.m_csNetInf.m_iNeuronNumber[m_csMyInf.m_csNetInf.m_lLayerNum - 1]; ll++)
                    {
                        msg += "[" + (m_csMyInf.dOnputData[ll] ).ToString() + "]";
                        if (csOutCell != null)
                        {
                            csOutCell[ll].m_dData[iPtn] = m_csMyInf.dOnputData[ll];
                        }
                    }
                    McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "Calculate", msg);
                }
                // 内部でデータジュージョンしてしまう
                if (m_csMyInf.RECOG_OUTPUT_PATTERN_ID >= 0)
                {
                    m_OutputCellData[m_csMyInf.RECOG_OUTPUT_PATTERN_ID].SendData();
                }

            }
            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "Calculate", "in");
            
            // To Do
            // 演算処理を行います。
            //m_csNeuralNetwaork.Learn();
            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "Calculate", "out");
            return 0;
        }

        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion(ref csOutputDataList)</para>
        /// </example>
        /// <param name="csOutputDataList">演算結果を公開する出力情報リスト</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override long DataFusion(ref HySDataLinkedList csOutputDataList)
        {
            // Do Nothing
            return 0;
        }
        /// <summary><para>method outline:</para>
        /// <para>モデル演算結果を外部のエレメントに対して公開する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>long lRtn = DataFusion( lOutputDataNum, ref csOutputCellData)</para>
        /// </example>
        /// <param name="lOutputDataNum">出力情報数</param>
        /// <param name="csOutputCellData">出力情報配列</param>
        /// <returns>=0:正常 -1:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        protected override long DataFusion(long lOutputDataNum, ref McSendCellDataIF[] csOutputCellData)
        {
            // Do Nothing
            return 0;
        }


        //====================
        // その他必要なメソッド
        //====================

        /// <summary><para>method outline:</para>
        /// <para>プロパティ情報を設定する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>SetProperty(csCellMdlPropertyInfo)</para>
        /// </example>
        /// <param name="csCellMdlPropertyInfo">セル型プロパティ情報</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool SetProperty(McCellModelPropertyIF csCellMdlPropertyInfo)
        {
            bool bRtn = false;
            // 使用しやすいようにキャストしておく
            m_csMyInf = (NeuralNetworkCalInfo)m_csCalInfo;

            // プロパティ設定
            McCellModelPropertyInfo csPrptyInfo = csCellMdlPropertyInfo as McCellModelPropertyInfo;
            if (csPrptyInfo != null)
            {
                // 演算ステップ時刻設定
                this.m_csDltTime = new HySTime(csPrptyInfo.GetStepTime());

                csPrptyInfo.GetInfo("m_lLayerNum", ref m_csMyInf.m_csNetInf.m_lLayerNum);
                m_csMyInf.m_csNetInf.m_iNeuronNumber = new int[m_csMyInf.m_csNetInf.m_lLayerNum];

                long lNeuronNumber = 0;
                csPrptyInfo.GetInfo("m_iNeuronNumber[0]", ref lNeuronNumber);
                m_csMyInf.m_csNetInf.m_iNeuronNumber[0] = (int)lNeuronNumber;
                csPrptyInfo.GetInfo("m_iNeuronNumber[Top]", ref lNeuronNumber);
                m_csMyInf.m_csNetInf.m_iNeuronNumber[m_csMyInf.m_csNetInf.m_lLayerNum - 1] = (int)lNeuronNumber;
                csPrptyInfo.GetInfo("m_iNeuronNumber[1]", ref lNeuronNumber);
                m_csMyInf.m_csNetInf.m_iNeuronNumber[1] = (int)lNeuronNumber;
                if (m_csMyInf.m_csNetInf.m_lLayerNum >= 4)
                {
                    csPrptyInfo.GetInfo("m_iNeuronNumber[2]", ref lNeuronNumber);
                    m_csMyInf.m_csNetInf.m_iNeuronNumber[2] = (int)lNeuronNumber;
                }
                m_csMyInf.dInputData = new double[m_csMyInf.m_csNetInf.m_iNeuronNumber[0]];
                m_csMyInf.dTchPtn = new double[m_csMyInf.m_csNetInf.m_iNeuronNumber[m_csMyInf.m_csNetInf.m_lLayerNum - 1]];
                m_csMyInf.dOnputData = new double[m_csMyInf.m_csNetInf.m_iNeuronNumber[m_csMyInf.m_csNetInf.m_lLayerNum - 1]];

                m_csNeuralNetwaork = new NN_NeuralNetwork(m_csMyInf.m_csNetInf.m_lLayerNum);
                for (int i = 0; i < (int)m_csMyInf.m_csNetInf.m_lLayerNum; i++)
                {
                    m_csNeuralNetwaork.SetLayerNeuronNum(i, m_csMyInf.m_csNetInf.m_iNeuronNumber[i]);
                }
                m_csNeuralNetwaork.CreateNeuralNetwork();
                m_csNeuralNetwaork.WeightInitialize(0.2, -0.2);


                bRtn = true;

                // To Do
                // モデルの係数等、必要な情報に対して、引数で与えられたプロパティ情報の内容を読み取って、設定します。
            }
            return bRtn;
        }

        /// <summary><para>method outline:</para>
        /// <para>計算開始時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = ReadyCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算開始の　最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool ReadyCalculation()
        {
            bool bRtn = true;
            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "ReadyCalculation", "in");
            if (m_csMyInf.m_lMode == 0)
            {   // 学習モード
                if (m_csMyInf.LEARN_INPUT_PATTERN_ID < 0 ||
                    m_csMyInf.LEARN_TEACH_PATTERN_ID < 0)
                {
                    bRtn = false;

                    // ver1.5 エラートレース日本語対応
                    McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "ReadyCalculation", Properties.Resources.STATEMENT_NOTSET);
                    McLog.DebugOut(new HySString(McLog.SYSTEM), new HySString("NeuralNetworkModel"), new HySString(Properties.Resources.STATEMENT_NOTSET));
                    //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "ReadyCalculation", "Learning pattarn is not set");
                    //McLog.DebugOut(new HySString(McLog.SYSTEM), new HySString("NeuralNetworkModel"), new HySString("Learning pattarn is not set"));
                }
            }
            else
            {   // 想起モード
                m_csNeuralNetwaork.SetLayerWeight(0, m_csMyInf.m_csNetInf.m_dW01);
                m_csNeuralNetwaork.SetLayerWeight(1, m_csMyInf.m_csNetInf.m_dW12);
                if (m_csMyInf.m_csNetInf.m_lLayerNum >= 4)
                {
                    m_csNeuralNetwaork.SetLayerWeight(2, m_csMyInf.m_csNetInf.m_dW23);
                }
            }
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>計算中断時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = SuspendCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>オペレーター操作等により計算中断時に　コールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool SuspendCalculation()
        {
            bool bRtn = true;

            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "SuspendCalculation", "in");

            // ToDo
            // オペレーター操作等により計算中断時に　コールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。
            // （メソッド自身を削除してください）

            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "SuspendCalculation", "out");
            return bRtn;
        }
        /// <summary><para>method outline:</para>
        /// <para>計算終了時に動作する処理</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = CompleteCalculation( )</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>true :正常 , false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>計算終了時　最後の最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。</para>
        /// </remarks>
        public override bool CompleteCalculation()
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "CompleteCalculation", "in");

            // ToDo
            // 計算終了時　最後の最初に１回だけコールされるメソッドです。不要ならば、本メソッドをオーバーライドする必要はありません。
            // （メソッド自身を削除してください）

            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "CompleteCalculation", "out");
            return true;
        }

        /// <summary><para>method outline:</para>
        /// <para>演算用刻み時間を自動的に変更する</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>ChangeDeltaTimeAutomatically()</para>
        /// </example>
        /// <param name="">無し</param>
        /// <returns>無し</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override void ChangeDeltaTimeAutomatically()
        {
            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "ChangeDeltaTimeAutomatically", "in");

            // ToDo
            // 演算中条件によって　自身のδTを(this.m_csDltTime) を変更するメソッドです。
            // 不要ならば、本メソッドをオーバーライドする必要はありません。（メソッド自身を削除してください）

            //McLog.DebugOut(GetSimulationTime(), GetID(), "NeuralNetworkModel", "ChangeDeltaTimeAutomatically", "out");
        }
               
        /// <summary><para>method outline:</para>
        /// <para>ファイルからモデル情報を全て読み出す</para>
        /// </summary>
        /// <example><para>usage:</para>
        /// <para>bool bRtn = FileIN(csData)</para>
        /// </example>
        /// <param name="csData">演算要素データ</param>
        /// <returns>=true:正常、=false:異常</returns>
        /// <exception cref="">無し</exception>
        /// <remarks><para>remarks:</para>
        /// <para>無し</para>
        /// </remarks>
        public override bool FileIN(CommonMP.HYSSOP.Interface.HSData.HySDataRoot csData)
        {
            bool bRtn = base.FileIN(csData);
            
            m_csNeuralNetwaork.SetLayerWeight(0, m_csMyInf.m_csNetInf.m_dW01);
            m_csNeuralNetwaork.SetLayerWeight(1, m_csMyInf.m_csNetInf.m_dW12);
            if (m_csMyInf.m_csNetInf.m_lLayerNum >= 4)
            {
                m_csNeuralNetwaork.SetLayerWeight(2, m_csMyInf.m_csNetInf.m_dW23);
            }
            return bRtn;
        }

    }
    //
}
