(前頁)<<      >>(次頁)          (Up)

6章 再び要素モデルの作成
6.2 色々な要素モデル   〜 デルファイ法によるシミュレーションモデルの構築 〜
(CommonMPを用いた 「森林等の経済シミュレーション」 を例にそれが可能か調べてみる)  その1


 未来を予測したり、計画の効果を見積もる場合に、シミュレーションが用いられます。  ある目的の評価用シミュレーションモデルを制作する場合を考えると、一人または数人の専門家が論理,アルゴリズムを考えてモデルを制作し、パラメーター値等も全て自作(または、委託製作)します。 シミュレーションモデルの仕様は独自であり、それを改善・修正する場合には、その中身を理解した人間でなければ、容易に行うことができません。 また、使用方法や、パラメータの与え方は独自仕様となるため、他の人々使い熟すためには、独自にそれらを習熟する必要があります。
 この為、シミュレーションを作成・使用する人の立場によって、一定の方向にバイアスが加わり、その人の意図に都合の良い前提条件やモデルパラメーターが使用される危険があります。 特に、シミュレーションモデルは複雑であればあるほど、他の人にはブラックボックス化して、異なる結果を示す色々なモデルが乱立してシミュレーション自体の信用性が著しく低下する事にもなります。

 CommonMPは、この様な状況に対して上手く対応できるシミュレーションツールです。
 
  CommonMPの特徴は 全ての機能を一つのモデルに纏めるのではなく、特定の機能を持つ「要素モデル」を色々と組み合わせて全体モデルを生成できる事にあります。 従って、次のような効果が期待できます。

(1)各要素モデルをその機能に詳しいそれぞれの専門家が作成し、全体を組み合わせることで、全体として専門家の知識を集めたシミュレーションモデルを構築できます(シナジー効果)。
(2)全体のシミュレーションモデルの構造が 各要素に分離して表わされるため、 モデルの全体構造を 直感的に把握することができます。
 また、使用されている要素モデル全ての内容に精通していなくてもモデルの概要を理解することが可能です。
(3)要素モデルは独自に開発して、別な要素モデルに置き換えることが可能であるため、要素モデルの比較ができます。
(4)必要に応じて、要素モデルの接続も変更できますが、全体はGUI上で表示されるため、変更箇所等が第3者にも、容易に理解できます。
(5)シミュレーションモデルは「プロジェクト」として纏めて公開でき、それらを他の人間がシミュレートすることが可能です。したがって、各人が、独自のパラメータを変更して検証することが可能です。
(6)公開された各要素モデルを組み合わせることで、要素モデル開発時には想定していなかったシミュレーションにも使用されて、全く新しいシミュレーションの開発が容易に行えるようになります。


 この様な特徴を活かすことで、次のように、公開の場で 多くの人々が共同でシミュレーションモデルを開発することが可能となります。
 
 例えば、ある事象を検証する目的でシミュレーションモデルをCommonMP上で構築し、公開したしたとします。
 それを使用した多くの人びとから、モデルの改善点や考慮不足部を指摘されたり、それらの意見を元に一部の要素モデルを提供する人が現われたりします。
 そして、それらの指摘事項に対応したり、提供された要素モデルを組み込んだりして、シミュレーションモデルを改善し公開します。
 改善して公開したモデルに対して、さらに色々な意見や改善された要素モデルが提供されたりという事を繰り返すことで、次第にそのモデルが改善されて、多くの人々から認められるモデルに成長していきます。

 この様な問題解決方法は、「デルファイ法による問題解決」に他なりません。

 つまり、あるテーマ(検証したいシミュレーション)に対して、専門家がそれぞれ意見を述べ(CommonMP上で自作または他作の要素モデルを使用して構築したモデルを公開)、 それらをフィードバック(公開モデルに対するいろいろな意見を自作の要素モデルに反映させる等)することで、次第にある一定の結論に収束していく(多くの人々に受け入れられるシミュレーションモデルが完成)という問題解決方法です。

 本来は、フォーラム等を開設して幅広く意見を求めるべきですが、その余力も無いので、ここでは、自作自演・一人芝居で 上記のようにデルファイ法によるCommonMPによるシミュレーションモデルの構築を行ってみます。

  本試みが成功するか否かは、わかりませんが、先ずは、ここで試してみたいと思います。


 テーマは、(2013年10月現在で)CommonMPの応用例が未だ存在しない、「経済的なモデル」を扱ってみます。


<製作シミュレーションのテーマ>
 豊かな森の存在が、農業、都市、漁業にまで大きな恩恵を与えていることを証明し、その豊かな森を守る為に、経済的にも持続可能な諸策を検討し、その効果をシミュレーションにより検証する。


(1)発起人 ・・・ 問題提起  森林の経済価値や存在意義をシミュレーションしたい

 「豊かな森林が国民の大きな財産であることは多くの方々が認識されていると思いますが、それがどのように国民に恩恵を与えているのか。また、それを保全し、次の世代に残すためにはどの様にすれば良いのか。 しかも経済的にも大きな負担を強いること無くそれは可能でしょうか?」
 「この様な事を シミュレーションを用いることによって研究したいと思います。 そこで、皆さんの叡智を集めて、上記目的に使用可能なシミュレーションモデルを作成し、その結果を元に討論したいので、 先ずは、そのシミュレーションモデル作成に協力して下さい。 シミュレーションモデルは CommonMPを用いて作成したいと思います。」

(2)A氏 ・・・ 必要な要素モデルの構造提案
 「簡単なモデルの構築から初めて、次第にそれを精製し、正確なモデルにしていく方が良いと思います。」
 「先ず、モデルは下に示す様な基本的な構造を提案します。」

  
                       基本的なモデルの考え方




   
            CommonMPで作成する要素モデルの基本
            (図のモデルを親として制作し、その派生で森林⇔林業、水田⇔農業等を作成する)   

 「上記構造に従って、 先ずは、親クラスを作成します。
 派生関係は以下のようにします。」

        
                          クラス派生関係


  「まずは、親クラスを作成し、親クラスのテストを行ってみました。 親クラスは abstract クラスとして作成したので、テスト用には、その派生クラス「mockクラス」を作成して、動作を確認しました。 mockクラスは下記の図の様に派生しました。 先ずは、親クラスを公開します。」
 
                           
       
                      制作した親クラスと テスト用mockクラス


 「以下、各要素モデルの親クラスと、mockクラス及び、テストプロジェクトを示します。」    

                     
                                                    経済要素モデル間の接続と動作の模式図 


 
 

                                       産業と消費者のテスト結果



                             
                                                    経済活動場と産業場の接続と動作の模式図 

     

 
    
                                       経済活動場と産業のテスト結果
 


             
                                                    自然(気象)と経済活動場の接続と動作の模式図



 

                                       自然(気象)と経済活動場のテスト結果
   


 「作成した要素モデルプロジェクトとテスト用のプロジェクトを下記に公開します。」

  Ex30_CommonMP.lzh
           ・プロジェクト名 : 「MyEconomicModel」
     ・テスト用CommonMPプロジェクト : 
                 「MyExerciseStep3\経済:親クラステストその1.cmprj」 
                 「MyExerciseStep3\経済:親クラステストその2.cmprj」
                 「MyExerciseStep3\経済:親クラステストその3.cmprj」 
  

 
             
                 プロジェクト内:リリースしたクラス

 解凍して作成された「MyEconomicModel」フォルダーを「CommonMP\Source\HYMCO\OptionImpl」 したにコピーし、   解凍して生成されたプロジェクト:MyEconomicModel.csproj を ディバッグ用ソリューションに追加し、スタートアッププロジェクト(TestModelDeveloperMainExp)の依存関係に追加します。
 また、 解凍して生成された、「MyExerciseStep3」フォルダーを \CommonMP\CommonMPData\ 下に置きます。 


(3)B氏 ・・・ A氏作成要素モデルへの提言 (複数の要素モデル接続の時、接続がどの要素モデルに接続しているかを識別する必要がある。)
 「A氏殿 要素モデル拝見しました。 ところで、ご提案の要素モデルですが、現在リリース頂いた要素モデルは、複数の経済要素モデルからの入力が存在した時それらを区別することが難しいと思います。 実際の経済要素モデルでは複数の要素モデルが網目の様に接続されて接続された要素が何であるか区別する機能が必要です。 例えば、 「A社」と「B社」から別々の注文を受けた場合、支払いは「A社」、「B社」では異なる品物や個数を納入する必要があります。 つまり、入力、出力がどの要素モデルに接続されているかを知り、「A社」からの注文であれば、「A社」に納入し、「A社」からの支払いを受けなければなりません。 そこで、各要素モデルの入力/出力先を区別できる機能を付けることは可能でしょうか?
      
       
                                          ↑ MyIndustoryModelは、A社、B社からの注文にそれぞれ答える必要がある


(4)A氏 ・・・ B氏提言への応答 (接続と要素モデルの対応識別機能を追加)
 「B氏殿 貴重なご意見有難うございました。 ご指摘の通り、接続している相手先の要素モデルを区別する必要があると思います。

  先ず、接続状態を整理します。
  MyEconomicModel同士の接続において、支払いは注文した側に行うものなので、2本に分かれている接続線を1本に纏めて、セル内変数を増やします。
  同様に、「MyIndustoryModel」→「MyFieldModel」接続における 作付作業、メインテナンス作業、刈り取り作業も同じ場所に接続するために1本の接続に纏めます。

 注文に対する納品の様に接続の向きが異なる場合には纏めることが出来ないので、モデル内で 対応表を作成する事にします。

(雑談)
 一本の接続線は、一方向にしか情報を流しません。 しかしながら、一本の接続線で上/下両方向に情報を流すことが可能であれば、便利です。 CommonMPのでは 将来そのような要求が発生する事も考慮し、「McMutualTranInfoImpl」クラスが準備されています。 このクラスの内部には 接続線を上下方向に1本づつ持つことが可能です。 このクラスは、Ver1.3現在 使用することはできません。

 次に、経済モデル(MyEconomicModel)間の接続は複数接続されることを考慮して、各入力接続、出力接続が どの要素モデルに接続しているかの対応表を作成します。
 対応表は下記メソッド内で生成します。
    /// 入力側の接続情報チェック
        protected override bool ReceiveConnectionCheck(ref McStructErrorInfo csErrorInf, long lInputDataNum, McReceiveCellDataIF[] csInputCellData)
        /// 出力側の接続情報チェック
        protected override bool SendConnectionCheck(ref McStructErrorInfo csErrorInf, long lOutputDataNum, McSendCellDataIF[] csOutputCellData)

 複数の要素モデルに接続している場合、入力情報に対して計算を行った結果は、同じ要素モデルに対応する出力線に出力されます。
 接続の対応は 下の様に 要素モデル計算データクラス内に対応表を作成します。

public class MyEconomicCalInfo : McCalInfo
{   
    // 接続テーブル
        public long m_lNumOfModelElement = 0;  // 関係する経済接続先要素モデルの数
        
        public long[] m_lInput_ModelNoTable;       // Input接続番号とモデル配列番号の対応
        
        public long[] m_lOutput_ModelNoTable;    // Output接続番号とモデル配列番号の対応
       
       。。。。。。。。。。。。。
 
 例として、下図に 2つの経済モデルとそれ以外の要素モデルに接続されている「中央の経済モデル:No2」内の対応表の値を示します。
  
                     入出力接続と経済モデルの対応 
                                       
 対応表内の 入力接続番号、出力接続番号、経済モデル番号は プログラム内で勝手に振られる番号であり、単なる対応関係を示す目印です。
 経済モデルNo:2に対して、 経済モデルNo:0からの入力は 入力2,入力3に入り、出力0から経済モデルNo:0へ出力されます。
 同様に、経済モデルNo:1からの入力は 入力4に入り、出力1から経済モデルNo:1へ出力されます。
 経済モデル以外からの入力出力はの対応モデル値は −1が設定されています。
 
 
    改造した経済要素モデルを使用したモデルを下図に示します。

   
  
 
 「作成した要素モデルプロジェクトとテスト用のプロジェクトを下記に公開します。」

  Ex31_CommonMP.lzh
           ・プロジェクト名 : 「MyEconomicModel」
     ・テスト用CommonMPプロジェクト : 
                 「MyExerciseStep3\経済:親クラステストその1.cmprj」 
                 「MyExerciseStep3\経済:親クラステストその2.cmprj」
                 「MyExerciseStep3\経済:親クラステストその3.cmprj」 
                 「MyExerciseStep3\経済:親クラステストその4.cmprj」 

  解凍して作成された「MyEconomicModel」フォルダーを「CommonMP\Source\HYMCO\OptionImpl」 したにコピーし、   解凍して生成されたプロジェクト:MyEconomicModel.csproj を ディバッグ用ソリューションに追加し、スタートアッププロジェクト(TestModelDeveloperMainExp)の依存関係に追加します。
 また、 解凍して生成された、「MyExerciseStep3」フォルダーを \CommonMP\CommonMPData\ 下に置きます。 



(5)C氏 ・・・ A氏モデルへの提言 (他の要素モデルからの受信情報の累積機能が必要)
 「A氏殿にリリースして頂いた要素モデルを使用して、森林関連のモデルを作成しようとしています。 ところで、 経済場要素モデルのδT を1週間、 産業要素モデルのδTを1日として動作させると、 産業モデルからの入力値を 経済場要素モデルが取りこぼしているようです。」


     

 「上図の様に産業要素モデルは1日毎に出力を行います。 しかし、場は7日毎に値を取得するため、残りの6日分の情報は取得されません。
 このため、要素モデルが使用する情報が瞬時値を使用するのではなく、累積値をしなければならない事にも対応する必要があると思います。
 例えば、毎日 1万円づつ支払っており、受け取り側が週に一度集計する要な場合には、1週間分の集計値を入力する必要があります。」

     


 「上記の通り、親クラスに入力値の集計を行うメソッドを取得することは可能でしょうか?」


(6)A氏 ・・・ C氏提言への応答 (受信情報の累積機能追加)
 「C氏殿 貴重なご意見有難うございました。 確かに、仰るとおり経済の情報では、内挿等を行うよりも、正確に受信した情報を取りこぼさずに累積するという事が必要と感じました。
 そこで、 親クラスに 「前回取得以降に受信した情報を全て累積する処理」、「前回取得以降に受信した情報の平均、最大、最小を計算する処理」を追加しました。」 

 「先ず、
 最後に送信されてきた情報を受信した時刻を計算データの中に覚えておくことにします。」
    [Serializable]
    public class MyEconomicCalInfo : McCalInfo
    {
    。。。。。。。。
        // 最終読み出し時刻
        public HySTime m_csLastReadTime = HySTime.DEFAULT_TIME.Clone();
    。。。。。。。。。

    }

 「受信下情報を読み取ったならば、この値を 現在のシミュレーションの時刻に設定します。
 次に受信する時には、この時刻(m_csLastReadTime )にあるレコードをすべて読みだして、累積値計算、平均値計算等を行えばよいわけです。

 MyEconomicModel、 MyFieldModel クラスに 累積値を計算するメソッドと、 平均、最大、最小値を計算するメソッドを下記の通り追加しました。」
 

        /// <summary>
        ///累積値計算
        /// </summary>
        /// <param name="csInputCellData"></param>
        /// <returns></returns>
        protected virtual HySCellData GetSumData(ref McReceiveCellDataIF csInputCellData);

       /// <summary>
        /// 平均、Max,Min値を求める
        /// </summary>
        /// <param name="csMeanCellD1"></param>
        /// <param name="csMaxCellD1"></param>
        /// <param name="csMinCellD1"></param>
        /// <param name="csInputCellData"></param>
        /// <param name="lDimInCellData"></param>
        protected virtual  void GetMaxMinData(ref HySCellData csMeanCellD1, ref HySCellData csMaxCellD1, ref HySCellData csMinCellD1, ref McReceiveCellDataIF csInputCellData,  long lDimInCellData);


   「読み出し方は、別の所(バイナリーファイル出力要素作成例) でも説明したので、簡単に復習します。
 
 最後に読みだした時刻(m_csLastReadTime)を引数として回線に SetCursorPlus(.m_csLastReadTime);として カーソル位置を 最後に読みだしたレコードの次の位置に置きます。
 ここから、最新のレコードまでを順に読み出していけば、 前回読み出し以後に追加されたレコードを全て取得できます。」

      
     


 「具体的ソースは ダウンロードしたソースの上記メソッド内を参照して下さい。
 
 追加した累積値を計算するメソッドと、 平均、最大、最小値を計算するメソッドの使用法の例を下記に示します。」

        protected virtual long PreCalculation(long lInputDataNum, ref McReceiveCellDataIF[] csInputCellData)
        {
            。。。。。。。。。。。。

            HySID csRcvID = null;
            for (long lLp = 0; lLp < lInputDataNum; lLp++)
            {
                csRcvID = csInputCellData[lLp].GetReceivePatternID();
                if (MyEconomicModelDefine.PATTERN_CLIMATE_IO.Equals(csRcvID) == true)
                {   // 気象
                    HySCellData csRcvCellData = this.GetSumData(ref csInputCellData[lLp]);  // 累積値計算 
                    m_csFieldInf.m_dRain = csInputCellData[lLp].Data(csRcvCellData, 1); // 雨量は累積値とする
                    m_csFieldInf.m_dDisaster = csInputCellData[lLp].Data(csRcvCellData, 3);

                    long lDimInCellData = 0;
                    long lCellDim = 0;
                    long lD2 = 0; long lD3 = 0;
                    long lDim1 = csInputCellData[lLp].GetDimension(ref lCellDim, ref lD2, ref lD3, ref lDimInCellData);

                    HySCellData csMeanCellD1 = new HySCellData(lDimInCellData);
                    HySCellData csMinCellD1 = new HySCellData(lDimInCellData);
                    HySCellData csMaxCellD1 = new HySCellData(lDimInCellData);

                    this.GetMaxMinData(ref csMeanCellD1, ref csMaxCellD1, ref csMinCellD1, ref csInputCellData[lLp], lDimInCellData);
                     m_csFieldInf.m_dSun = csInputCellData[lLp].Data(csMeanCellD1, 0); // 日照率は平均値とする。
                    m_csFieldInf.m_dTemperature = csInputCellData[lLp].Data(csMeanCellD1, 2);  // 気温平均値
                    m_csFieldInf.m_dMaxTemp = csInputCellData[lLp].Data(csMaxCellD1, 2); // 気温最大値
                    m_csFieldInf.m_dMinTemp = csInputCellData[lLp].Data(csMinCellD1, 2); // 気温最小値
                }

       。。。。。。。。。


 (注意)接続線のレコード数の設定には注意する必要があります。 例えば、前要素モデルのδTが1日で 後要素モデルのδTが30日の場合とした時、接続線のレコード数は 最低でも30必要です。10レコードの場合には、累積数が20日分不足します。 CommonMPではレコード数を自動で最適化する機能がありますが、今回のモデルはループが存在するため、累積値を計算するには適しません。 従って、手動で設定する必要があります。

 
  「作成した要素モデルプロジェクトとテスト用のプロジェクトを下記に公開します。」

  Ex32_CommonMP.lzh
           ・プロジェクト名 : 「MyEconomicModel」
     ・テスト用CommonMPプロジェクト : 
                 「MyExerciseStep3\経済:親クラステストその1.cmprj」 
                 「MyExerciseStep3\経済:親クラステストその2.cmprj」
                 「MyExerciseStep3\経済:親クラステストその3.cmprj」 
                 「MyExerciseStep3\経済:親クラステストその4.cmprj」 

  解凍して作成された「MyEconomicModel」フォルダーを「CommonMP\Source\HYMCO\OptionImpl」 したにコピーし、   解凍して生成されたプロジェクト:MyEconomicModel.csproj を ディバッグ用ソリューションに追加し、スタートアッププロジェクト(TestModelDeveloperMainExp)の依存関係に追加します。
 また、 解凍して生成された、「MyExerciseStep3」フォルダーを \CommonMP\CommonMPData\ 下に置きます。 

続く


(前頁)<<      >>(次頁) 

初版:2013/10/16 |第3版:2013/11/29