1

FSM(EDIT:Finite State Machine)状態をどのように実装しますか?私は通常、FSMを一連の関数、ディスパッチャー、スレッドのように、現在の実行状態を示すものと考えています。つまり、状態を表す関数/ファンクターへの呼び出しをブロックします。

ちょうど今、私は別のスタイルで1つを実装しました。ここでは、関数(オブジェクト)で状態を表しますが、スレッドはstate->step()メソッドを呼び出すだけで、できるだけ早く戻ります。状態が終了し、遷移が発生する必要がある場合は、それに応じてそれを示します。関数はほとんど次のように見えるので、これを「ポーリング」スタイルと呼びます。

void step()
{
  if(!HaveReachedGoal)
  {
    doWhateverNecessary();
    return; // get out as fast as possible
  }
  // ... test perhaps some more subgoals
  indicateTransition();
}

FSM内のFSMであることを認識しています。

かなり単純に感じますが、特定の利点があります。スレッドがブロックされたり、ある種の while (!CanGoForward)checkGoForward(); ループに保持されたりするのは面倒で扱いにくい場合がありますが、ポーリングはデバッグがはるかに簡単であると感じました。これは、FSMオブジェクトがすべてのステップの後に制御を取り戻すためであり、デバッグ情報を出力するのは簡単です。

さて、私は私の質問から逸脱しています:FSMの状態をどのように実装しますか?

4

5 に答える 5

1

私がフライングスパゲッティモンスターのFSMを実装するスタイル(FSMスタイルのFSM)と呼ぶものは常にあります:lotsaを使用しgotoます。例えば:

state1:
  do_something();
  goto state2;

state2:
  if (condition) goto state1;
  else           goto state3;

state3:
  accept;

とても素敵なスパゲッティコード:-)

于 2010-06-21T11:28:17.477 に答える
1

私はそれをテーブル、メモリ内のフラット配列として行いました。各セルは状態です。放棄されたDFAプロジェクトのcvsソースをご覧ください。:_

class DFA {
    DFA();
    DFA(int mychar_groups,int mycharmap[256],int myi_state);
    ~DFA();
    void add_trans(unsigned int from,char sym,unsigned int to);
    void add_trans(unsigned int from,unsigned int symn,unsigned int to);
    /*adds a transition between state from to state to*/
    int add_state(bool accepting=false);
    int to(int state, int symn);
    int to(int state, char sym);
    void set_char(char used_chars[],int);
    void set_char(set<char> char_set);
    vector<int > table; /*contains the table of the dfa itself*/
    void normalize();

    vector<unsigned int> char_map;
    unsigned int char_groups; /*number of characters the DFA uses,
                    char_groups=0 means 1 character group is used*/
    unsigned int i_state; /*initial state of the DFA*/
    void switch_table_state(int first,int sec);
    unsigned int num_states;
    set<int > accepting_states;
};

しかし、これは非常に特定のニーズのためでした(正規表現に一致する)

于 2010-06-21T11:28:22.507 に答える
1

state Design Pattern は、FSM を実装する興味深い方法です。

http://en.wikipedia.org/wiki/State_pattern

これは FSM を実装するための非常にクリーンな方法ですが、FSM の複雑さ (状態の量ではない) によっては面倒になる可能性があります。ただし、利点は次のとおりです。

  • コードの重複を排除します (特に if/else ステートメント)
  • 新しい状態で拡張する方が簡単です
  • クラスのまとまりが良くなるため、関連するすべてのロジックが 1 か所にまとめられます。これにより、コードのテストも書きやすくなります。

このサイトには、Java および C++ の実装があります。

http://www.vincehuston.org/dp/state.html

于 2010-06-21T11:33:08.817 に答える
1

最初の FSM プログラムを覚えています。非常に単純なswitchステートメントを使用して C で記述しました。ある状態から別の状態への切り替え、または次の状態への移行は自然に思えました。

次に、テーブル ルックアップ アプローチを使用するようになりました。このアプローチを使用して、非常に一般的なコーディング スタイルを書くことができました。ただし、要件が変更され、いくつかの追加イベントをサポートする必要が生じたときに、何度か追い詰められました。

最近、FSM を書いていません。私が最後に書いたのは、C++ の通信モジュール用で、「コマンド パターン」(アクション)と組み合わせて「状態設計パターン」を使用しました。

于 2010-06-21T12:47:24.063 に答える
0

複雑なステート マシンを作成している場合は、SMC (State Machine Compiler) を調べてみてください。これは、ステート マシンのテキスト表現を受け取り、選択した言語にコンパイルします。Java、C、C++、C#、Python、Ruby、Scala などをサポートします。

于 2010-06-21T12:16:33.803 に答える