GitHubで「ステートマシン」のいくつかの実装を見てきました。私が理解している限り、ステートマシンは、その状態を他の有限集合の1つに変換する場合と変換しない場合がある入力を受け取ります。それは他のコンピュータプログラムとどう違うのですか?
GitHubで「ステートマシン」のいくつかの実装を見てきました。私が理解している限り、ステートマシンは、その状態を他の有限集合の1つに変換する場合と変換しない場合がある入力を受け取ります。それは他のコンピュータプログラムとどう違うのですか?
回答:
あなたが本当に知識をひけらかすようにしたい場合は、すべてのコンピュータープログラムを使用すると、コンピュータに宇宙全体ですべての問題を変換する場合でも、それがされますので、有限状態マシンでまだのみ、これ状態の有限量、および有限の有限のメモリを持っていますそれらの状態間の遷移の量。
ステートマシンは、ラムダ計算、チューリングマシン、ランダムアクセスマシン、アクターシステム、オブジェクトシステムなどのモデルです。一部の問題は、状態機械によってモデル化されることに向いていますが、そうでないものもあります。
ビジネスプロセスは、コンピューターが存在する前から、ステートマシンとしてモデル化されることがよくありました。彼らはそのような考え方に自然に向いています。
理論的な観点から見ると、まったく同じです。もちろん、理論的な観点からは、アセンブリ言語で任意のプログラムを書くことができ、それも同様に機能します。
コードが実行されているコンピューターは、他のコンピューターで実行される他のプログラムと同様に、非常に複雑なステートマシンと数学的に同等である可能性がありますが、最もエレガントな解決策が状態とトランジションには、プログラマーが(コンパイラーやハードウェアデザイナーとは対照的に)思いついたドメイン固有の意味があります。
たとえば、正規表現を実装する古典的な方法の1つは、正規表現を有限状態マシンの仕様として解釈し、そのようなマシンを構築してから、文字列をフィードしてacceptまたはrejectすることです。より一般的には、プログラム内のオブジェクトが常に有限数の状態の1つを持ち、それらの状態間の遷移が常に特定の方法で発生するように強制する場合は常に、状態マシンの構築が最もエレガントなソリューションになる可能性があります。
状態機械は、その状態を他の有限集合の1つに変換する場合と変換しない場合がある入力を受け取ります。それは他のコンピュータプログラムとどう違うのですか?
ここでのいくつかの回答は、私たちの(おそらく)有限な宇宙ではすべてが有限であり、すべてのコンピュータープログラムが有限の時間で実行されるため、厳密にはすべてが有限状態マシンであることを強調しています。それは「技術的に正しい(最良の種類の正しい)」ですが、ポイントを完全に逃しています。
本質はこれです:-一部のコンピュータープログラムは、より大きく複雑な入力を取得するときに、より多くの作業メモリを必要とします。一部ではありません。
これに気づくと、理論的な情報に基づく洞察を得て、特定の種類の問題が発生したときに、より効率的でエレガントなプログラムを作成できるようになります。また、これが適用される可能性のある問題の種類を認識することもできます。
2つのおもちゃの例を次に示します。
問題1:プログラムが標準入力で文字のリストを受け取ります。すべての文字が処理された後、プログラムは、入力の「x」文字の数が奇数か偶数かを出力する必要があります。
問題2:プログラムが標準入力で文字のリストを受け取ります。すべての文字が処理された後、プログラムは、入力の「x」文字の数が「y」文字の数よりも少ないか、等しいか、または多いかを出力する必要があります。
今すぐ読むのをやめて、お気に入りのプログラミング言語(または疑似コード)で問題を解決して、後で戻ってくることもできます。
...
あなたが気づいたかもしれない重要なことは次のとおりです:問題1の解決策を適切に実装するには、1ビットのメモリしか必要ありません。すでに処理した「x」の数を計算する必要はありません。これまでに処理された「x」の数が奇数か偶数かだけです。別の「x」に遭遇したら、ビットを反転します。プログラムの最後に、ビットを見て答えを印刷します。
入力に数十の文字が含まれていますか?何千人ものキャラクター?Googolplexキャラクター(もちろん、仮説的に言えば)?関係ない; 作業用メモリは1ビットで十分です。
問題2では同じことはできません。文字を読み取るときは、処理済みの「x」と「y」の数の違いを覚えておく必要があります。そうしないと、正しい答えを確実に印刷できません。「x」と「y」の両方の数を実際に覚える必要はないことに気づくかもしれません。これまでのところ、それらの違いだけです。別の "x"に遭遇すると増加し、別の "y"に遭遇すると減少する1つの整数値-ただし、たとえばこの値を保持するために32ビットのメモリを使用する場合、入力(数十億文字の長さ)が、限られたメモリ量では正しく処理できません。
これは、問題1は「ステートマシン」で解決でき、問題2は解決できないという意味です。任意のサイズの入力には、限られた量のメモリで十分です。
(もちろん、問題1の非効率的なソリューションを作成して、すべての「x」を数えようとすると、メモリ不足の問題が発生する可能性もあります。ただし、違いは問題1に対する効率的な解決策は存在しますが、問題2に対する同様に効率的な解決策は存在しません。
なぜこれが現実の生活で重要なのですか?
まず、これら2つのおもちゃの例とは異なり、ジレンマは文字通り1ビットと1つの整数値の間ではなく、いくつかの大きなデータ構造とさらに大きなデータ構造の間の可能性があります。現実的な入力であっても、「さらに大きい」データ構造がコンピュータのメモリに収まらない場合や、プログラムの速度が十分に低下する場合があります。
第二に、状態マシンを使用するソリューションはおそらくはるかに高速になります。また、入力の長さに応じて線形にスケーリングします。つまり、10倍長い入力の処理には、10倍の時間が必要になります(たとえば、100倍の時間とは異なります)。これは、大量のデータを処理する必要がある場合に望ましいプロパティです。
3番目に、メモリ使用量の制限と無制限はセキュリティに影響します。限られたメモリしか必要としないプログラムを作成する場合は、メモリオーバーフローや、システム全体のセキュリティを侵害するためにメモリオーバーフローが悪用される可能性について心配する必要はありません。
第4に、これは適切な学校の標準的なコンピュータサイエンスカリキュラムの一部です。形式言語、オーソマタ、計算の複雑さなどです。コンピュータデザインの全体像を理解するために、単に「ええと、インターネットからいくつかのコードを組み合わせたのですが、実際に機能することを願っていますが、確実にはわかりません」というアプローチです。
この理論を利用するには、特別なマシン、フレームワーク、ライブラリは必要ありません。「ああ、問題のこの部分は有限のメモリを使用して実際に解決できる」と認識して書くだけです。それに応じて(お気に入りのプログラミング言語で)プログラムを作成します。ただし、状況によっては、既存のライブラリを使用した方がよい場合があるため、ホイールを再発明する必要はありません。
他の答えが指摘したように、状態機械について特別なことは何もありません。ただし、プログラムがFSMを実装していることを明示的に述べることはしばしば有益です。
プログラミングは、問題に適した抽象化を見つけることから成り立っています。抽象化を使用することは、実装の観点ではなく抽象化の観点から話すことを意味します。多くのプロセスは本質的にステートフルです。たとえば、Webサイトでのサインアッププロセスや、eコマースアプリケーションでのチェックアウトプロセスなどです。これらのプロセスをモデル化する場合、矢印で接続されたボックスをホワイトボード(状態図)に描画します。ここで、状態機械は一種の設計パターンであり、状態機械について話すことは私の意図を同僚に明確に伝えるでしょう。
命令型プログラムは本質的にステートフルであるため、状態を導入するときに常に気づくわけではありません。たとえばC言語では、セミコロン演算子などの特定の言語構成要素が「シーケンスポイント」をマークします。これは状態遷移であり、操作間の順序付けを強制します。Haskellなどの純粋な関数型言語などの環境や、HTTPなどのステートレスプロトコルを使用する場合は、状況が異なります。突然、すべての状態が明示的になる必要があり、ステートマシンとして設計を明示的に表現すると、管理しやすくなります。
有限状態機械は正規表現に対応するため、解析において重要な役割を果たします。いくつかの正規表現を手動で実装すると、非常に複雑なコードが生成される可能性があり、最悪の場合は正しくさえありません。ステートマシンを実装していることに気付いた場合、さまざまな既知の実装手法を使用して支援することができます。たとえば、状態を明示的にして、現在の状態を変数に格納できます。あるいは、言語の制御フローを通じて状態を暗黙的にすることもできます。私はさまざまな状況で両方を実行しましたが、無制限のプログラムではなく、状態マシン(制限された状態遷移、開始状態、既知の終了状態、再帰なし、永続的なデータ割り当てによる暗黙の状態なし)を実装していると述べています実装と理解が容易になります。
私が知っているすべてのプログラミング言語は、その言語でステートマシンを正確かつ効率的に表現することを容易にするため、ステートマシンライブラリを使用することはめったにありません。ただし、例外があります。決定論的オートマトンは実装が簡単ですが、非決定論的オートマトンはかなり重要です。なぜなら、状態マシンは同時に複数の状態になる可能性があるためです。NFAを実装または書き換えるライブラリを使用すると、これらの問題を無視して、実際に重要なことに集中できます。
設計としてのステートマシンの使用と、コンピューターサイエンスおよび言語理論におけるステートマシンの使用を超えて、実際にはそれほど多くの使用はありません。ステートフルな論理回路が思い浮かびます。プログラマーにとってのステートマシンの主な用途は、状態と状態遷移の観点から考えることを学ぶことです。私のプログラムには暗黙の状態がありますか?すべての状態遷移を正しく実装しましたか?私は何かを見逃して、無効な状態を開きましたか?オブジェクトのメンバーフィールドは状態に対応し、メソッドは状態遷移に影響を与える可能性があるため、このような考え方はオブジェクト指向プログラミングで特に重要になります。オブジェクトにステートマシンを明示的に実装することはためらいますが、それでも、ステートマシンは動作に適したメンタルモデルになる可能性があります。
ステートマシンライブラリを作成する主な理由は、トピックを確実に理解するためですが、ほとんどのアプリケーションでは、それらを必要としないか、手動でロールします。