fc2ブログ

ネタつつき198 - 立法システムはどうあるべきか

 以前日本の国家システムについて書きましたので、今回は立法システムについて書きます。結論から言いますと、日本の立法システムは最悪です。これから、その理由と改善案を書きます。
 立法システムの役割とは何でしょうか?私は「良質な法律を生産する」だと思います。リソース配分や外交的なこともしていますが、システムではそれ自体が間違いであり、法律の生産能力を第一に考えるべきだと私は思います。
 立法府をシステム的に考えると、問題発生件数 < 立法生産能力 でないと、国が停滞するのは明白です。しかしながら、現在の日本はこの立法生産能力が限りなく低い状態で、毎年問題が増えています。これは、「みんなで決める」という、集団作業の弱点をそのまま行っているのが原因だと思います。また、立法にかかわる人の報酬、権限、責任のバランスが滅茶苦茶なのも原因だと思います。
 集団だから何でもよいというのではありません。集団作業をしても、逆に生産能力が下がる方法があります。それが今、日本の立法府がしていることです。集団作業の弊害は、交渉コストが高すぎて、生産できない事です。まさしく日本ではそうです。衆参合わせて722人のうち過半数が合意するまで法律が作れないというのは、非常に非生産的です。さらにいえば、議員立法と内閣立法の過程において、合意交渉が多すぎます。日本の企業の意思決定が遅すぎて、世界では戦えないのと同じ理由だと思います。
 さらに悪いことに、集団作業では責任がうやむやになる性質があります。現状でも、どれだけ悪法を立法しても、だれも責任を取りません。また、報酬が一定なので、立法を妨害したり、選挙活動という名の就職活動に専念したりしていても、一定の報酬が自動で貰える状態です。立法しても報酬が増えないので、国会議員が生産能力をアップさせようと、真剣に考えるはずがありません。集団作業における悪い面が全てあらわれているのが日本の現状です。
 こういうことを書くと、民主主義とはそういうものだという人がいるでしょう。しかし、民主主義=非生産的ということはありません。アメリカの民主主義は日本よりもスピーディです。日本の民主主義の生産効率が悪いだけなのです。非常に憂慮するべき惨状です。
 日本は法治国家なので、全ての問題が法に帰します。その法律の生産能力が低いのですから、不景気になるのも当然ですし、自殺者数が3万人を超え、原発問題や年金問題が解決しないのも至極当然だと言えるでしょう。
 では、どうすればいいのかといいますと、平行処理をすればいいと思います。個々の議員が責任を明確に持ち、平行的に作業することにより法律の生産能力は確実にアップします。生産能力に応じて報酬が定まるようにすれば、自然と生産能力もアップします。そもそも、「みんなで同じことを考える」という日本の悪習が効率を悪くしています。責任をもって、分担作業して初めて集団作業の長所が生まれます。
 アベノミクスに足りないのは、こういった自己改善です。不備があるシステムの上で、当事者がそれを考えられないのは当然なので、私たち国民が考えるべき事柄です。やる気がある議員がこういった事柄を発案しても、さぼっている議員が妨害するでしょう。楽して儲かるシステムがある以上、それを改善できないのは人間の性だと思います。期待して待っていても、自ら楽に儲かる状態を放棄するとは考えられません。
 さらに悪いのが、固定人数だという点です。固定人数だということは、資質がない議員でも当選してしまうことを意味します。さらにその悪い議員が投票権を握っているので、よい法律を効率よく生産できないのは当たり前です。議員が善人である確率が50%だとします。ということは、2の722乗分の1の確率でしかよい構成員が得られないということになります。要法律ができる確率は、それ掛ける適切な判断を下せる確率です。722人が法律にかかわるすべての事象を賢明に判断できる確率は何%でしょうか?そもそも、全ての事象を理解している国会議員は一人でもいるのでしょうか?そんな奇跡を待っている間に日本は滅んでしまいます。日本が衰退しているのは、明らかにこの立法システムが酷すぎるのが原因です。お上任せという行為は、奇跡を信じて待つ行為にほかなりません。国は奇跡で維持できません。国が滅んで困るのは国民です。海外に逃げても、国が滅べば奴隷扱いされるのが関の山です。国を失った民族が何をされるのかは、歴史で証明されています。国民はこの事実から目を背けずに、真剣に考えるべきだと私は思います。
スポンサーサイト



テーマ : 政治・時事問題
ジャンル : 政治・経済

計算機の基本原理を味わおう22 - どこまでリファクタリングするのか考えよう

 この記事は、計算機の基本原理を味わおう21 - オブジェクトの役割をきっちり決めて結合度を下げようの続きです。前回は、オブジェクトの結合度に関する事柄を解説しました。今回は、リファクタリングのゴールについて解説します。
 どこまで、リファクタリングすればよいのかという質問をよく受けるので、今回はリファクタリングのゴールについて書きます。最終的なリファクタリングのゴールはありません。何故ならば、そのシステムが使われ続け、ヴァージョンアップし続ける限り、リファクタリングの必要性があるからです。しかしながら、一時的なゴールがないと大変心細いです。リファクタリングは職人的な作業であり、熟練者は感覚的に理解していますが、慣れていない人はわからないようです。それはよくない状態ですので目安を書きます。
 リファクタリングの目安は、オブジェクトを参照するコードが明瞭簡潔である状態になるまでです。「明瞭簡潔」もまた、感覚的な問題をはらんでいますが、コードは目に見えるので、感覚よりもましだと思います。
 具体例として、この連載で作成している最小計算機のサンプルコードをもとに考えてみましょう。

using System;
using System.Diagnostics;
using MiniBitMachine;
using MiniBitMachine.V3;
using MiniBitMachine.V3.Utility;

class Sample
{
    //命令をテストする。
    private static ExecutionResult Execute(
        IfCode code,
        Cpu cpu )
    {
        cpu.Reset();
        code.SaveData();
        Console.WriteLine( code.Name + "命令を実行します・・・" );
        Console.WriteLine( "---------- 実行前 ---------- " );
        Console.WriteLine( code.ToString( "v" ) );
        ExecutionResult result = cpu.AllRun();
        Console.WriteLine( "----------  実行後 ---------- " );
        Console.WriteLine( code.ToString( "v" ) );
        Console.WriteLine( "----------  状態 ---------- " );
        Console.WriteLine( result );
        Debug.Assert( !code.CheckData() );
        return result;
    }

    //テストプログラムの開始部分
    private static void TestMain(
        Cpu cpu, 
        IfCode code )
    {
        code.SetBinary();
        Console.WriteLine(
            "********** " + code.Name + "命令の内容 **********" );
        Console.WriteLine( Cpu.GetEnvironment() );
        Console.Write( cpu );
        Console.Write( code.ToString( "a" ) );
        Console.WriteLine( );
        Console.Write( code.ToString( "d" ) );
        Console.WriteLine( );
        ExecutionResult result;
        result = Execute( code, cpu );
        result += Execute( code, cpu );
        Console.WriteLine( "★★★★★ 総計 ★★★★★" );
        Console.WriteLine( result );
    }

    //inc命令のテストを行う。
    private static void IncTest( Memory m )
    {
        byte ds = 1;
        byte cs = 2;
        Cpu cpu = new Cpu( ds, cs, m );
        byte carryFlagAddress = 4;
        byte targetAddress = 3;
        Inc inc = new Inc(
            targetAddress,
            carryFlagAddress,
            cpu );
        TestMain( cpu, inc );
        Console.WriteLine();
    }

    //not命令のテストを行う。
    private static void NotTest( Memory m )
    {
        byte ds = 3;
        byte cs = 4;
        Cpu cpu = new Cpu( ds, cs, m );
        byte targetAddress = 3;
        Not not = new Not(
            targetAddress,
            cpu );
        TestMain( cpu, not );
        Console.WriteLine();
    }

    static void Main()
    {
        Memory m = new Memory();
        IncTest( m );
        NotTest( m );
        Console.ReadLine();
    }
}

大体これぐらい参照する側のコードが減ればいいと思います。このコードを実装するために、オブジェクトの階層化をし、書式文字を受け付けるToStringメソッドを用意しました。
 リファクタリングでオブジェクトの継承を使用するのは、ちょっと難易度が高いし、本来はオブジェクト指向設計で決めておくべきなのですが、全てが設計段階でわかりません。柔軟にオブジェクト指向プログラミング → オブジェクト指向設計 → オブジェクト指向プログラミングというふうに、行動を切り替えましょう。そもそも、オブジェクト指向は、ウォーターフォールモデルで開発するものではなく、改善を積み重ねて行うものですから、これがオブジェクト指向本来の姿です。
 サンプルコードにあるIfCodeオブジェクトは、NotとIncオブジェクトの親です。両オブジェクトがif構造に基づいて構築されており、ほかにもif構造のオブジェクトが考えられるので作成しました。IfCodeオブジェクトは次のようにしています。

using System;
using System.Collections.Generic;
using System.Linq;

namespace MiniBitMachine.V3
{
    //If文により構築されている命令を表すオブジェクト。
    public abstract class IfCode : CompositeInstruction
    {
        //inc命令を構成するcmov群。
        protected If _if;

        //インスタンスを生成する。
        public IfCode( string name ) : base( name ) { }

        //命令を生成する。
        protected void CreateInstruction(
            Cpu cpu,
            bool addLast) 
        {
            CompareMove[] compareCodes = GetCompareCodes();
            CompareMove[] trueCodes = GetTrueCodes();
            CompareMove[] falseCodes = GetFalseCodes();
            this._if = new If(
                cpu,
                compareCodes,
                trueCodes,
                falseCodes,
                addLast);
            this.Compares = this._if.Compares;
        }

        //比較フラグ設定に関するコードを取得する。
        protected abstract CompareMove[] GetCompareCodes();

        //比較対象が真の場合に実行するコードを取得する。
        protected abstract CompareMove[] GetTrueCodes();

        //比較対象が偽の場合に実行するコードを取得する。
        protected abstract CompareMove[] GetFalseCodes();

        //インスタンスの文字列表現を取得する。
        public override string ToString()
        {
            return this._if.ToString();
        }


        //インスタンスの文字列表現を取得する。
        public string ToString( string value )
        {
            switch ( value ) {
                case "v":
                    return GetValueString();
                case "d":
                    return this._if.ToString();
                case "a":
                    return GetAddressString();
                default:
                    throw new FormatException(
                        "書式" + value + "には対応してません。" );
            }
        }

        //アドレスを表すインスタンスを取得する。
        protected abstract string GetAddressString( );

        //値を表すインスタンスを取得する。
        protected abstract string GetValueString( );
        
        //オブジェクトが持つ各種値を保存する。
        internal abstract void SaveData( );

        //オブジェクトが保持している値と、現在値を比べ、
        //同じ値ならばtrueを返す。
        internal abstract bool CheckData( );

        //自身のバイナリ値をメモリにセットする。
        public void SetBinary()
        {
            this._if.SetBinary();
        }
    }
}

参考のためにIncオブジェクトも掲載します。

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

namespace MiniBitMachine.V3
{
    //inc(インクリメント)命令
    public sealed class Inc : IfCode
    {
        //命令を実行するCPU。
        private Cpu _cpu;

        //実行環境に関する情報。
        private ExecuteEnvironment _info;

        //対象のアドレス。
        private byte _targetAddress;
        public byte TargetAddress
        {
            get { return this._targetAddress; }
        }

        //対象の値
        public bool TargetValue
        {
            get { return this._cpu.ReferenceMemory.Read( 
                this._cpu.Addresser.GetDataAddress( 
                    this._targetAddress ) ); }
        }

        //保存している値。
        private bool _saveValue;

        //桁上がりを表わすフラグの場所。
        private byte _carryFlagAddress;
        public byte CarryFlagAddress
        {
            get { return this._carryFlagAddress; }
        }

        //桁上がりを表わすフラグの値。
        public bool CarryFlagValue
        {
            get 
            {
                ushort address = 
                    this._cpu.Addresser.GetDataAddress(
                        this._carryFlagAddress );
                return this._cpu.ReferenceMemory.Read( address );
            }
        }

        //保存しているキャリーフラグの値。
        private bool _saveCarryFlag;

        //対象のアドレス、桁上がりフラグのアドレス、
        //CPUの情報、を元に、インスタンスを生成する。
        public Inc(
            byte targetAddress,
            byte carryFlagAddress,
            Cpu cpu)
            : this( targetAddress, carryFlagAddress, cpu, true )
        {
        }

        //対象のアドレス、桁上がりフラグのアドレス、
        //CPUの情報、を元に、インスタンスを生成する。
        public Inc( 
            byte targetAddress, 
            byte carryFlagAddress, 
            Cpu cpu, 
            bool addLast ) : base( "inc" )
        {
            this._targetAddress = targetAddress;
            this._carryFlagAddress = carryFlagAddress;
            this._cpu = cpu;
            this._info = Cpu.GetEnvironment();
            this.CreateInstruction(cpu, addLast );
        }

        //比較フラグ設定に関するコードを取得する。
        protected override CompareMove[ ] GetCompareCodes( )
        {
            CompareMove[ ] result = new CompareMove[ 1 ];
            result[ 0 ] = new CompareMove(
                this._info.CompareFlagAddress,
                this._targetAddress,
                "実行フラグの場所に対象データを移動" );
            return result;
        }

        //比較対象が真の場合に実行するコードを取得する。
        protected override CompareMove[ ] GetTrueCodes()
        {
            CompareMove[] result = new CompareMove[ 2 ];
            result[ 0 ] = new CompareMove(
                this._targetAddress,
                this._info.OneAddress,
                "対象を1に設定" );
            result[ 1 ] = new CompareMove(
                this._carryFlagAddress,
                this._info.ZeroAddress,
                "桁上がりフラグを0に設定" );
            return result;
        }

        //比較対象が偽の場合に実行するコードを取得する。
        protected override CompareMove[ ] GetFalseCodes()
        {
            CompareMove[ ] result = new CompareMove[ 2 ];
            result[ 0 ] = new CompareMove(
                this._targetAddress,
                this._info.ZeroAddress,
                "対象を0に設定" );
            result[ 1 ] = new CompareMove(
                this._carryFlagAddress,
                this._info.OneAddress,
                "桁上がりフラグを1に設定" );
            return result;
        }

        //アドレスを表すインスタンスを取得する。
        protected override string GetAddressString( )
        {
            System.Text.StringBuilder result = new System.Text.StringBuilder();
            result.Append( "対象アドレス:" );
            result.Append( this.TargetAddress );
            result.Append( Environment.NewLine );
            result.Append( "桁上がりフラグのアドレス:" );
            result.Append( this.CarryFlagAddress );
            result.Append( Environment.NewLine );
            return result.ToString();
        }

        //値を表すインスタンスを取得する。
        protected override string GetValueString( )
        {
            System.Text.StringBuilder result = new System.Text.StringBuilder();
            result.Append( "対象値:" );
            result.Append( this.TargetValue );
            result.Append( Environment.NewLine );
            result.Append( "桁上がりフラグ:" );
            result.Append( this.CarryFlagValue );
            result.Append( Environment.NewLine );
            return result.ToString();
        }

        //オブジェクトが持つ各種値を保存する。
        internal override void SaveData( )
        {
            this._saveValue = this.TargetValue;
            this._saveCarryFlag = this.CarryFlagValue;
        }

        //オブジェクトが保持している値と、現在値を比べ、
        //同じ値ならばtrueを返す。
        internal override bool CheckData( ) 
        {
            if ( this._saveValue == this.TargetValue ) return true;
            if ( this._saveCarryFlag == this.CarryFlagValue & 
                this._saveValue  ) return true;
            return false;
        }
    }
}

なお、CompositeInstructionオブジェクトは、IfとIfCodeの親であり、命令を表すInstructionオブジェクトの子です。両オブジェクトは現在のところ、タグ的な意味合いが強いですが、機能が追加されるにつれて、大きな力を発揮すると思います。
 今回はこれで終わりです。Hello worldプログラムよりも量が多いプログラミングをするとき、リファクタリングは避けられません。特にこういった学習のためのプログラミングでは、リファクタリングの腕が学習効果に結び付くと思います。リファクタリング力をアップさせて、プログラミング力もアップさせましょう。続く...

テーマ : プログラミング
ジャンル : コンピュータ

ネタつつき197 - 現実のアルゴリズム停止性

 チューリングマシンの停止問題は、理論的には面白いのですが、実務的にはすぐに溶ける問題ですし、直接の役に立たないので、実務的な停止問題について考察しました。結論から言いますと、停止問題は確率の問題だと思います。
 考察に当たり、最初に停止問題の定義を考えてみましょう。計算機が停止するとはどういう意味でしょうか?私が思うに、終了状態に状態遷移できないことだと思います。具体的には、アルゴリズムの次のステップに進めない、循環ループしている、永遠に入力待ちにしている・・・などの状態です。一緒に個々の状況を考えてみましょう。
 一番多いのが、循環ループなどの理由で、終了状態に状態遷移できない状態です。これは、ループを脱出する条件を満たさない事が原因です。状態遷移木を作って探索すると検出できるでしょう。
 厄介なのは、人間の手が介入したときです。例えば、ユーザーが忘れて、ダイアログのボタンを押すなどといった、求められた操作をしないとき、アルゴリズムは前に進みません。これは機械的には解決できない問題です。制限時間を過ぎたら自動的にOKとみなす、などといった対策は可能ですが、心理的にはあまり好ましい解決方法でありません。後で勝手に処理をしたと怒られるかもしれません。
 他にもさまざまな要因が考えられます。ネットワークでパケットが紛失した、CPUが熱暴走した、HDDが破損した、怒った妹にPCを壊された、猫にESCボタンを押された、クラッカーにやられた、必要なファイルを消された・・・などといったことが起こるかもしれません。これも、広い意味で停止問題だといえるでしょう。
 これらの事例を考えてわかることは、真偽の2値ではなく、0以上1.0以下の浮動小数で表したほうが現実に即しているということです。文章ではわかりにくいと思いますので、実際に計算してみましょう。
 アルゴリズムXがあるとします。このアルゴリズムXは4つのステップA~Dで成り立っています。A:開始状態( 1.0 )、B:入力値待ち( 0.8 )、C:変換処理( 0,9 )、D:終了状態( 1.0 )だと仮定します。Bは10回に2回ユーザーに無視され、Cは10回に1回変換ミスで処理がストップするとします。このアルゴリズムの停止性は、1-( 1.0 * 0,8 * 0.9 * 1.0 ) =  1 - 0.72 = 0.18です。従ってアルゴリズムXは18%の確率で停止します。書き直したほうがよいでしょう。
 現実的な停止問題を考えるうえで、もう一つ考えるべきことがあります。それは、「区間」です。10日停止しないのと、100年停止しないアルゴリズムには天と地の差があります。基準となる区間をはっきりしないと、停止度を計算できません。
 察しがいい人は気付いたと思いますが、この問題は耐故障性と関連が深いと思います。ただし、故障していなくてもアルゴリズムが停止しないこともあるので、今回述べた停止性の一部が故障性だと考えるとよいと思います。
現実は複雑なので、すべての事象を列挙できないので、正確に求めることは不可能に近いですが、概算でいいのでアルゴリズムの停止性について考えると、よいシステムを構築が出来上がる確率が増えます。がむしゃらにアジャイル開発するのではなく、たまには立ち止まって、理論をじっくりと考えることも必要だと私は思います。

テーマ : プログラミング
ジャンル : コンピュータ

ネタつつき196 - 日本の国家システムはどうあるべきか

 私はよくこのブログで、日本の国家システムが酷すぎて、それが多くの社会問題を生んでいると発言しています。何かを非難するときは、対論を出すのが、社会人としての礼儀であると私は考えているので、国家システムについて考えてみました。
 国家システムを考える際には、要求分析をしなければなりません。しかしながら、我々日本人はこの部分がお上任せなので、要求そのものがはっきりしません。しかしながら、それでは話が前に進みませんので、自分の要求をもとに話を展開していきます。
 私が国家に臨むのは、OSとしての機能です。すなわち、極力低コストで、国民の生命と財産を守る役割を果たすシステムを求めています。国家とは何か、それを考えるのは意外と難しいですが、OSとして考えればよいというのが私の持論です。理由は、外交問題、国内問題、経済問題にあります。
 社会問題で論点となるのは、国民の財産と生命を守れるか否かです。私は戦争を望みませんので、戦争を避けたり、国際紛争に巻き込まれたりしないためにも、原則を定めないとなりません。現状のように曖昧模糊な状態ですと、なし崩し的に戦争に突入する可能性が高いです。憲法9条さえ守っていればよいと考える人もいますが、他国の人は憲法9条を無視することもできますし、好戦的な党が憲法解釈により、無理やり戦争を起こす可能性が十分にあります。それ故に、そうならないように、正しくシステム化しておかねばなりなりません。
 国内問題で論点になるのも、やはり国民の生命と財産です。犯罪により不幸な目に遭う国民をなくす機能(防犯機能)、発生してから事件を解決する機能が、国家システムには必要です。現状は「民事不介入」の名のもとに、満足に防犯する機能がありません。現在は残念ながら、罪なき国民と真面目に働く警察にとって不幸な状況だといえます。
 経済問題については、日本は何故か「自分を儲けさせろ」という我田引水的な思考が基本となっていますが、自由経済が基本の昨今において、時代錯誤な考え方です。政府に儲けさせてもらうのではなく、自分たちが儲けると考えるのが自然です。そのためには、ブラック企業や、資本の暴力を防ぐための機能が必要です。これもまた、国民の生命と財産を守る機能だといえます。
 以上で伝わると思いますが、国家システムは「国民の生命と財産を守る」の1点だけ考えて、構築すればよいのです。それ故にOSだと私は表現しています。現在の日本は農奴制を採用した封建社会ですが、今の時代ではナンセンスです。利権を求めてあれこれ余計なものを政府に求め、その結果コストが高く、処理能力が低い状態になったのが、現在の日本の国家システムです。お上にしてもらおうという発想は捨て、「自分たちがやるから必要最低限のサポートしてほしい」という発想でこれからの日本を築いていくのがベストだと私は考えている次第です。

テーマ : 政治・時事問題
ジャンル : 政治・経済

計算機の基本原理を味わおう21 - オブジェクトの役割をきっちり決めて結合度を下げよう

 この記事は、計算機の基本原理を味わおう20 - 状態遷移と停止問題について考えようの続きです。前回は、停止問題について解説しました。今回は、オブジェクトの結合度に関する事柄を解説します。
 サンプルコードの量が増えてきたので、オブジェクト指向プログラミングをする上で避けては通れない、オブジェクトの結合度について考えてみましょう。オブジェクトの結合度というのは、簡潔に表現すると、オブジェクトがどれだけ他のオブジェクトを参照しているか、もしくは参照されているのかを表す概念です。この連載で扱っているサンプルコードは、まだ大した量ではありませんが、コード量が少ない段階から考えていくほうがよいです。何故ならば、コード量が多くなってから結合度について考えると、構造が把握し難く失敗しやすいからです。本来はオブジェクト指向設計で考えるのが良いのですが、プログラミングしている段階でも考えるべきです。
 具体的に考えていきます。最少計算機で気になるのは、CompareMoveオブジェクト(比較移動命令)の結合度が高い点です。現在の実装はメモリの読み書きに限定されていますが、比較移動本来の動きは、メモリに限ったものではありません。本来するべきことは、値を移動(コピー)するだけなので、メモリ以外でも実行できるようにしたほうがよいといえます。
 オブジェクトの結合度を低くするためには、インタフェースを定義し、それを参照するのがよいでしょう。

using System;

namespace MiniBitMachine.V3
{
    //命令の値(オペランド)が持つべきインタフェースの定義。
    public interface IOperand
    {
        ushort Value { get; set; }
    }
}

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

namespace MiniBitMachine.V3
{
    //比較移動命令。
    public class CompareMove : 
        Instruction, 
        IEquatable
    {
        //関係のないメンバーは省略

        //命令長。
        public static int Length { get { return 16; } }

        //比較フラグ
        private bool _compareFlag;
        public bool CompareFlag
        {
            get { return this._compareFlag; }
            set { this._compareFlag = value; }
        }

        //宛先。
        private IEnumerable _destinationBinary;
        private IOperand _destination;
        public IOperand Destination
        {
            get { return this._destination; }
            internal set { this._destination = value; }
        }

        //送信元。
        private IEnumerable _sourceBinary;
        private IOperand _source;
        public IOperand Source
        {
            get { return this._source; }
            internal set { this._source = value; }
        }

        //インスタンスを生成する。
        public CompareMove() : this( null, null, "" )
        {
        }

        //宛先と送信元を指定してインスタンスを生成する。
        public CompareMove( IOperand destination, IOperand source )
            : this( destination, source, "" )
        {
        }

        //宛先と送信元とコメントを指定してインスタンスを生成する。
        public CompareMove(
            byte destination,
            byte source,
            string comment )
        {
            this._destinationBinary =
                BitMaster.ConvertBinary( destination );
            this._destination = new Immediate( destination );
            this._sourceBinary =
                BitMaster.ConvertBinary( source );
            this._source = new Immediate( source );
            this.Comment = comment;
        }

        //宛先と送信元とコメントを指定してインスタンスを生成する。
        public CompareMove( 
            IOperand destination, 
            IOperand source, 
            string comment )
        {
            if ( destination != null ) 
                this._destinationBinary =
                    BitMaster.ConvertBinary( ( byte ) destination.Value );
            this._destination = destination;
            if ( source != null )
                this._sourceBinary =
                    BitMaster.ConvertBinary( ( byte ) source.Value );
            this._source = source;
            this.Comment = comment;
        }

        //バイナリ値からインスタンスを生成する。
        public CompareMove( IEnumerable binary )
        {
            if ( binary.Count( ) != CompareMove.Length )
                throw new ArgumentException(
                    String.Format(
                        "必ず{0}ビットの値を指定してください。",
                        CompareMove.Length ) );
            this._destinationBinary =
                binary.Where(
                    ( b, index ) =>
                        ( index < 8 ) ).Select( b => b );
            this._destination = new Immediate( 
                BitMaster.ConvertToByte( this._destinationBinary ) );
            this._sourceBinary =
                binary.Where(
                    ( b, index ) =>
                        ( index >= 8 ) ).Select( b => b );
            this._source = new Immediate( 
                BitMaster.ConvertToByte( this._sourceBinary ) );
        }

        //命令を実行する。
        public virtual void Execute()
        {
            if ( this._compareFlag )
                this.Destination.Value = this.Source.Value;
        }

    }
}

これで値を持つオブジェクトに対して、比較移動を使用できるようになりました。比較移動命令を変更すると、実行部分を変更する必要が生じるのでます。その方法として、実行を担当するExecuterオブジェクトを変更する手もありますが、それでは実行と解析の役割を兼用することになってしまいます。何故ならば、インタフェースを実装するオブジェクトを設定するコードドが必要になるからです。
 では、どうすればよいのでしょうか?こんな時は、オブジェクトが持つ役割は1つだと考えるとよいでしょう。ですから今回ベストな方法は、解析を担当するDecoderオブジェクトを定義することだと思います。実装なこんな具合になります・・・

using System;
using System.Collections.Generic;

namespace MiniBitMachine.V3
{
    //命令を解析するオブジェクト。
    public class Decoder
    {
        //実行に必要な情報。
        ExecuteEnvironment _exeInfo;

        //アドレスを管理するオブジェクト。
        Addresser _addresser;

        //解析に必要な情報を指定し、
        //インスタンスを生成する。
        public Decoder(
            ExecuteEnvironment exeInfo, 
            Addresser addresser )
        {
            this._addresser = addresser;
            this._exeInfo = exeInfo;
        }

        //命令をデコードする。
        public CompareMove Decode( IEnumerable<bool> binary )
        {
            CompareMove temp = new CompareMove( binary );
            CompareMove result = this.SetOperand( temp );
            return result;
        }

        //オペランドを設定する。
        private CompareMove SetOperand( CompareMove command )
        {
            if ( command.Destination.Value ==
                this._exeInfo.CompareFlagAddress ) {
                    return SetCompareFlagOperand( command );
            } else if ( command.Destination.Value ==
                    this._exeInfo.ProgramCounterAddress ) {
                        return SetProgramCounterOperand( command );
            } else if ( command.Destination.Value ==
                this._exeInfo.LastAddress ) {
                    return SetStopCpuOperand( command );
            } else {
                return SetMemoryOperand( command );
            }
        }

        //比較フラグに関するオペランドを用意する。
        private CompareMove SetCompareFlagOperand( CompareMove command )
        {
            command.CompareFlag = true;
            command.Destination = this._exeInfo.CompareFlag;
            command.Source = this.GetSource( command );
            return command;
        }

        //プログラムカウンタに関するオペランドを用意する。
        private CompareMove SetProgramCounterOperand( CompareMove command )
        {
            command.CompareFlag = this._exeInfo.GetCompareFlag();
            command.Destination = this._addresser.ProgramCounter;
            return command;
        }

        //CPU停止に関するオペランドを用意する。
        private CompareMove SetStopCpuOperand( CompareMove command )
        {
            command.CompareFlag = false;
            this._exeInfo.IsStop.Value = 1;
            command.Source = this.GetSource( command );
            return command;
        }

        //メモリに関するオペランドを用意する。
        private CompareMove SetMemoryOperand( CompareMove command )
        {
            MemorySnapShot destination = 
                new MemorySnapShot( 
                    this._addresser, 
                    this._exeInfo.ReferenceMemory, 
                    command.Destination.Value );
            command.CompareFlag = this._exeInfo.GetCompareFlag( );
            command.Destination = destination;
            command.Source = new Immediate( command.Source.Value );
            return command;
        }

        //メモリ用のソースを取得する。
        private IOperand GetSource( CompareMove command )
        {
            IOperand result = new MemorySnapShot(
                    this._addresser,
                    this._exeInfo.ReferenceMemory,
                    command.Source.Value );
            return result;
        }

    }
}

さらにやるべきことがあります。それは、レジスタオブジェクトと、メモリの一時状態(スナップショット)が必要です。なぜならば、IOperandインタフェースを実装しないと、比較移動命令に指定できないからです。
 以上のように、オブジェクトの結合度を低く保つには、ある程度の作業と新しいオブジェクトが必要となります。面倒だと思う人もいるでしょうが、結合度が高いオブジェクトを保守することを考えれば、無視できるコストです。必要ならば、一時的な労力を惜しんではなりません。プログラミングでは、将来のコストを下げるために、今コストがかかってもするのが原則です。覚えておくとよいと思います。続く...

テーマ : プログラミング
ジャンル : コンピュータ

ネタつつき195 - 大半の社会問題は日本人の思考法のバグが原因

 私はシステム屋ですので、日々のニュースを聞きながら、個々のニュースではなく、それら日本の社会問題の根源を考えていました。システム屋はシステム思考をしますので、個々の事例(インスタンス)ではなく、問題の発生源を根絶することを考えます。今の日本は、そういった考えが足りないと思いましたので、この記事を書くことにしました。
 日本は毎日同じようなニュースが報道されているにもかかわらず、社会問題は一向に解決しません。その原因について私が導き出した結論は、「日本人の思考法そのものにバグ(間違い)がある」です。今からその理由を述べます。
 たとえば、今話題になっている原発問題はなぜ起きているのでしょうか?表面的に見れば、原発村の人々の行動が原因に見えます。確かにこれは大きな問題です。彼らが多くの国民に対して害を与えるモンスターシステムを構築し、維持しているせいで、福島で原発事故という名の人災が起こりました。しかし、私はそれが問題の本質だとは思いません。何故ならば、そのモンスターシステムを許容しているのは、他でもない我々国民だからです。
 原発の人災が起こる前に、我々国民は電力問題について、どれほど真面目に考えていたでしょうか?私は皆無だと思います。もし国民全員が真剣に考えていれば、モンスターシステムは構築不可能でしたし、福島の原発問題(人災)は起こりませんでした。それ以前に、モンスターシステムを構築する理由すらなかったと思えてなりません。
 日本では建前と本音の乖離が激しいです。なおかつ、綺麗な建前だけを取り繕うことしか考えていません。綺麗な建前だけで済むほど現実は甘くありません。しかしながら、我々国民は綺麗な建前だけに満足して、現実を直視していません。どれだけ問題が起ころうとも、「お上に任せていればよくなる。少なくとも自分だけは安全だ。」と日本人は考えています。福島の原発事故(人災)ですら他人事です。口では助け合いだとか、絆だとか言っていますが、真剣に問題を考えていません。その証拠に、問題を起こした当事者である、電力会社と政府に任せっきりです。問題を起こした本人に期待して、待っているだけで事がうまくいくなんて事はありえません。言葉は悪いですが、テロリストに対して、黙っていれば「良きに計らってくれる」もしくは「自分だけは見逃してくれる。」と考えているのと同じです。それで上手くいくと本気で考えている日本人の思考法そのものがバグにほかなりません。
 先ほどのたとえは少々言葉が悪いのですが、現実問題、当事者に問題解決能力がないのは明白です。電力会社に問題解決能力があれば、そもそも、人災が原因の原発事故は起こりません。また、政府に問題解決能力があれば、人災を防げたのは明白ですし、2年以上かかっても解決できない何てことはあり得ません。また、原発事故は福島だけで済むと考えるのは、非理論的すぎます。福島の原発だけが特別だと考えるのは、明らかにおかしいので、全国の問題だと考えるのが妥当です。従って、民主主義の主役である我々国民が、思考放棄せずに、電力、安全性、政府の能力などについて、真剣に考えるべきなのです。
 本質的なことを言えば、現実を見ず、建前だけを考えているから何の問題も解決できないのです。どれほど綺麗な看板を立てても、現実に起こる問題を解決しなければ話になりません。具体的にいうと、モンスターシステムが必要になったのは、政治家、電力会社、官僚といった人々が、綺麗ごとではなく、正しく儲けられるに、国家システムを整備しておかなかったのが問題の根本です。現実を見ないから、何をしても儲かる、いやそれどころか、現実には守れない綺麗ごとではなく、国民に対して害をもたらす方法のほうが儲かるという状態にしてしまったのです。
 日本では、人と役職を見て問題を論じます。しかしながら、そういった視点は無意味です。悪いことをしたほうが儲かり、その行為ができてしまうのであれば、誰かが必ずその悪事を働きます。たまたまその人がやっただけなので、悪い人は誰かと論じるのは全くの無意味で、悪いことができないシステムを構築しなければなりません。
 さらに悪いことに、日本は現実を無視した綺麗な建前を作り、建前を現実に守れず、隠蔽と悪事で儲けるのが常習化しています。これは非常に馬鹿げたことです。最初から現実を見つめ、実行できる状態にしないとなりません。
 纏めると、我々日本人は、現実を直視せず、建前だけを取り繕うことしか考えておらず、思考放棄してあり得ない願望を抱きつつ、漫然と暮らしているといえます。社会問題はすべての人が影響を受けます。自分だけは安全だとか関係ないと考えず、真剣に物事を考えましょう。それは、社会人として当たり前の行為であり、いい加減に現実を直視できる大人になるべきではないでしょうか?

テーマ : 政治・時事問題
ジャンル : 政治・経済

書籍をつつく153 - 建前の裏側を垣間見れる良書

ここ最近で一番面白かったのがこの本です。




この本は原発村の生態を描いた本です。その描写が実にリアルです。
大大の想像はついていましたが、こうやって改めて読むと、背筋が寒くなります。
ホラー小説よりも怖かったです。
それにしても、日本の国家システムは本当に酷い状態です。
問題の本質は「思考停止」にあると思います。
原発村の人を擁護するつもりは毛頭ありませんが、国民が何も考えなければ、こうなるのは自明です。
人間は理想で飯を食えません。善人に利益を悪人に不利益を与えるシステムを構築していないから、飯を食うために、悪貨が良貨を駆逐するのは当たり前です。
私もその「考えない国民」のうちの一人なので反省しました。
今のままだと、原発事故が多発してもおかしくありません。
何はともあれ、日本人の基礎教養として、原発問題は知っておいたほうがいいと思います。
この本を読んで、報道されていない本音を知りましょう。

テーマ : 政治・時事問題
ジャンル : 政治・経済

中の人の徒然草476

 昨日こんな本があるのを知りました。




すごく気になります。買って読もうかな?
そにしても、この本の概要を読んだだけでも、日本の国家システムが既に破綻していることがわかります。なぜ日本はお上任せで何もしないのか、不思議でなりません。お上任せにして、放射能をもらい、増税され、ひたすら国民の生命と財産が危険にされされ続ける・・・
私たち国民は真正のマゾなのでしょうか?これでは、お金を払って危険を買っているのと同じです。
やはり誰かに任して、思考停止すると、一部の人間に対して良きに計られますね。
思考停止した民衆が、民主主義をするとどうなるのか、日本はそれを如実に表わしていると思います。
何時まで日本は封権社会をするのでしょうか...非常に情けないです。

テーマ : 日記
ジャンル : 日記

ネタつつき194 - チューリングマシンの停止問題から見える仕様定義/分析/設計能力

 チューリングマシンの停止問題は、仕様定義能力、分析能力、設計能力、実装能力などの総合能力が試されます。これは大変面白い事なので、チューリングマシンの停止問題における、上流部分(仕様定義、分析、設計)を考えてみましょう。
 私は職業柄、こうしたことは得意で、チューリングマシンの停止問題を読んで1分未満で、実務的に解く方法がわかりました。こういった類の問題は、システム屋が毎日している事なので、一応の答えを出すことは簡単です。では、どうやって考えたのか、興味がある人が居るかもしれませんので書きます。
 チューリングマシンの停止問題で実務的に考えるべきことは、何が求められているのかです。チューリングマシンの停止問題で要求されているのは、停止の有無を判定するアルゴリズムです。では、アルゴリズムとは何か、それから考えねばなりません。
 アルゴリズムを簡潔に述べると、有限回数で答えを出す方法です。従って、求められている事は、任意の与えられたアルゴリズムの停止の有無を、有限回数で決定する方法です。これが決まれば8割ぐらい終わったといえます。要求がわかれば、答えを用意することは比較的簡単です。何故ならば、現実の問題は要求を捉えることそのものが難しいからです。
 次に考えるべきことは、チューリングマシンの仕様です。チューリングマシンは、有限制御部、入力テープ、テープヘッドから構成される計算モデルです。そして、形式的には、状態、テープ記号、空白記号、入力記号集合、動作関数、初期状態、受理状態の集合からなります。加えて、手続きは有限で、機械的に実行できるステップでなければならないという制約もあります。これらの条件を踏まえ、そこからオブジェクトを導き出しつつ、アルゴリズムを解くことになります。
 最後に考えねばならないのは、チューリングマシンを処理するチューリングマシンと、そのチューリングマシンに渡されるチューリングマシンのどちらが上位かという事です。求められているのは、チューリングマシンの停止有無を判定する、チューリングマシン用のアルゴリズムなので、チューリングマシンを処理するチューリングマシンの方が上位です。上位が決まれば、有限回数かつ機械的なステップで解く方法を導き出せます。
 ここまで分かれば後は簡単です。循環ループにならないようにアルゴリズムを設計するだけです。何故ならば、チューリングマシンを処理するチューリグンマシンの要求定義が、必ず最後は停止するとなっているからです。また、上位であるという事は、引数として渡されるチューリングマシンを制御できるという事を意味しますので、それが決まった時点で答えは明白だといえるでしょう。
 このチューリングマシンの停止問題は、数学的には背理法で矛盾していると導きだされるのですが、これに疑問を持てるか否かで、実務能力に差が出ると思います。この論法には明らかにミスがあります。それは、入力値を無視している点と、渡されるチューリグンマシンの動作と、処理する側のチューリングマシンの動作が同一視されている点です。また、どうやって値を返すのかが曖昧です。これだけ定義が厳密に定められていないのですから、たとえ数学的には通用しても、実務では通用しません。私は数学とはもっと厳密的なものだと思っていたのですが、意外と曖昧なようです。数学はプログラミングよりも宣言的なのです。ヒルベルトさんの気持ちがわかるような気がします。
 現実は宣言的に論理的矛盾している事柄によく遭遇します。しかし、論理的に矛盾していると思考停止してはなりません。人間は論理的に矛盾していることをよく要求します。従って、論理的に矛盾していることに対して、如何にして答えを提供するのかが我々の課題であり、それをできる能力が実務能力だといえます。実務家にとって論理的矛盾は出発点です。思考停止せず、より深く考え続けましょう。

テーマ : プログラミング
ジャンル : コンピュータ

ネタつつき193 - チューリングマシンの停止問題を実務的に解く

 現実で起こる問題は、チューリングマシンの停止問題のような、矛盾に満ちています。しかしながら、現実は矛盾しているといって終われるほど簡単なものではありません。情報システムを開発業務をしていると、矛盾がデフォルトの状態になります。人間ははえてして矛盾したことを望むものです。従って、理論的には矛盾していることが明白なことに対しても、実務ではそれなりの答えを出さねばなりません。今回はそれを踏まえて、チューリングマシンの停止問題を実務的に解くことを目指します。最初に断わっておきますが、この記事で言っている解法は、数学的ではありません。あくまでも、現実にある問題を解くための実務的な考え方を述べています。
 まずは、チューリングマシンの停止問題を知らない人のために、簡潔にこの問題を書きます。チューリングマシンの停止問題とは、チューリングマシンMと記号列wからなる対( M, w )を受け取り、停止するならばYesを、停止しないならばNoを返すチューリングマシンMwを定義する。このチューリングマシンMwに対して、いかなる入力値( M, w )に対しても答えを出せるアルゴリズムが、あるか否かを決定する問題です。
 チューリングマシンの停止問題は、計算論的には決定不能であるとされています。何故ならば、入力値として、Mwと反対に動くMを定義すれば、どちらの結果にしても矛盾が生じるからです。つまり、MwがYesを返す場合Mは停止せず、MwがNoを返す場合Mは停止しますです。なんと厄介なチューリングマシンなのでしょう!この結果は、理論的に矛盾しているので、Mwの存在自体があり得ないと結論付けできます。まぁ、妥当な理論だと思います。しかし実務ではそれで済ませられません。「解法がわからないからお前に依頼しているんだ。」と言われるだけです。従って、どうにかして矛盾を克服せねばなりません。これから、チューリングマシンの停止問題を、強引に解いていきます。
 まずは、矛盾の原因を探ります。矛盾の要因は明らかに、MがMwを参照している事です。しかし、アルゴリズムは、有限回数で解かねばなりませんので、どちらか先に答えを出さねばなりません。その考えを元に、私ならば次のアルゴリズムを設計します・・・

【停止判定アルゴリズム】
0、各オブジェクトを初期化する。
1、MがMwを参照しているか否かを判定する。参照しているならば手順2へ飛ぶ。
 参照していないならば手順4へ飛ぶ。
2、Mwに入力値wを入力する。それをMに渡す値Yとする。
3、手順5へ飛ぶ。
4、入力値をMに渡す値Yとする。
5、Yを適用しMが無限ループするならばNo、しないならばYesを返却値として設定。
6、Mを終了。
7、返却値を返す。

簡単なアルゴリズムなので、内容をすぐに理解できると思います。内容を簡潔に言うと、ただのnot論理演算子です。Mwは任意のMを入力値して指定できる時点で、Mw自身を参照している可能性を考えねばなりません。ならば、想定外を想定し、それを判定すればいいだけです。これで一応解決できます。数学的には反則なような気がしますが、綺麗な理論だけでは現実で通用しません。
 今回の記事いかがでしたか?あまりスマートではありませんが、矛盾を解くには、強引な解法が必要です。理論に傾倒せず、柔軟に物事を考えれば、どんな決定不可能な問題でも解けると思います。現実は理論的に矛盾している事の方が多いので、理論に拘らず臨機応変に行動しましょう。そうすれば、答えは必ずあるのです。

テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

インドリ

Author:インドリ
みなさん、はじめまして、
コンニチハ。

ボクは、無限の夢(infinity dream)を持つネタ好きな虹色の鳥インドリ(in dre)です。
色々な情報処理技術を啄ばむから楽しみにしてね。

http://twitter.com/indori
は別人による嫌がらせ行為です。
私とは関係ないので注意して下さい。
次はなりすましブログなどをするかもしれませんが、ここ以外でブログをするつもりがないので、ここ以外にインドリのブログがあったとしても無視してください。


何度言っても分からない人がいるので、ここにコメント欄へ書き込むときの注意事項を書きます。


一、社会人としてのマナーをわきまえましょう。
一、妄想に基づく書き込みを止めてください。
一、暴言の類は書かないで下さい。
一、某誹謗中傷サイトの書き込みは彼らの妄想に基づく書き込みですから無視して、ここへ書き込まないで下さい。
一、コメント書く前に他のコメントよく読んでから行って下さい。
一、言いがかかり等の行為を禁止します。
一、その他常識的に考えて迷惑なコメントはしないで下さい。


以上のルールを守れない人のコメントは削除します。



利用上の注意
ここに紹介してある文章およびプログラムコードは正確であるように心がけておりますが、内容を保証するものではありません。当サイトの内容によって生じた損害については、一切の責任を負いませんので御了承ください。


執筆したCodeZineの記事


【VB.NETで仮想CPUを作ろう】

  1. VB.NETで仮想CPUを作ろう
  2. レジスタの実装
  3. 仮想CPUのGUI化
  4. テストドライバの改良
  5. CPUの基礎動作の実装
  6. MOV命令の実装
  7. ADD命令実装
  8. SUB命令実装
  9. INC命令&DEC命令の実装と命令長
  10. MLU命令の実装とModR/Mについて
  11. DIV命令の実装とイベント設計について
  12. 機械語駆動式 関数電卓を作ろう!
  13. 機械語駆動式 関数電卓を作ろう! 解答編(前半)
  14. 機械語駆動式 関数電卓を作ろう! 解答編(後半)


【仮想ネットワーク実装でTCP/IPを学ぼう】
  1. TCP/IPの基礎と勘所
  2. ネットワークアクセス層の勘所
  3. インターネット層の勘所
  4. トランスポート層の勘所
  5. アプリケーション層の勘所
  6. セキュリティの基礎と仮想ネットワークの仕様
  7. GDI+と独自プロトコルの定義



【並列化】
インテル Parallel Studioを使って並列化プログラミングを試してみた
並列プログラミングの効率的なデバッグを実現する「Parallel Inspector」


【TBBシリーズ】
  1. インテル スレッディング・ビルディング・ブロックの概要
  2. インテルTBBから学ぶループの並列化
  3. スレッドセーフとインテルTBBのコンテナ
  4. インテルTBBのスレッドクラス


【OpenMPシリーズ】
  1. OpenMPの基礎構文
  2. OpenMPの実行時ライブラリと並列ループ
  3. OpenMPのメモリモデルとfork- joinモデル

最近の記事
最近のコメント
月別アーカイブ
カテゴリ
Ada (9)
COBOL (5)
C (9)
C++ (11)
C# (370)
D (25)
Java (8)
Perl (1)
Ruby (14)
PHP (2)
Boo (2)
Cobra (2)
LISP (6)
F# (33)
HTML (0)
XHTML (0)
CSS (0)
XML (0)
XSLT (0)
Scala (4)
WPF (0)
WF (2)
WCF (0)
LINQ (4)
MONO (5)
Linux (0)
MySQL (0)
ブログ内検索
リンク
最近のトラックバック
RSSフィード
ブロとも申請フォーム

この人とブロともになる

QRコード
FC2カウンター