FSM数据结构设计
我想编写一个 FSM,它从空闲状态开始,并根据某些事件从一种状态移动到另一种状态。 我不熟悉 FSM 的编码,谷歌没有帮助。 如果有人可以发布可用于相同目的的 C 数据结构,我将不胜感激。
谢谢, 苏加2012
I want to write an FSM which starts with an idle state and moves from one state to another based on some event. I am not familiar with coding of FSM and google didn't help.
Appreciate if someone could post the C data structure that could be used for the same.
Thanks,
syuga2012
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
有限状态机由有限数量的离散状态组成(我知道这很迂腐,但仍然如此),它们通常可以表示为整数值。 在 C 或 C++ 中使用枚举非常常见。
机器响应有限数量的输入,这些输入通常可以用另一个整数值变量表示。 在更复杂的情况下,您可以使用结构来表示输入状态。
内部状态和外部输入的每种组合都会导致机器:
c 中的一个简单情况可能如下所示,
尽管这很难阅读,并且更容易通过以下方式拆分为多个函数
:每个状态的复杂性取决于其自身的功能。
正如 m3rLinEz 所说,您可以在数组中保存转换以进行快速索引。 您还可以将函数指针保存在数组中以有效地处理操作阶段。 这对于自动生成大型且复杂的状态机特别有用。
A finite state machine consists of a finite number discrete of states (I know pedantic, but still), which can generally be represented as integer values. In c or c++ using an enumeration is very common.
The machine responds to a finite number of inputs which can often be represented with another integer valued variable. In more complicated cases you can use a structure to represent the input state.
Each combination of internal state and external input will cause the machine to:
A simple case in c might look like this
though this is hard to read and more easily split into multiple function by something like:
with the complexities of each state held in it's own function.
As m3rLinEz says, you can hold transitions in an array for quick indexing. You can also hold function pointer in an array to efficiently handle the action phase. This is especially useful for automatic generation of large and complex state machines.
这里的答案看起来非常复杂(但仍然准确)。所以这是我的想法。
首先,我喜欢 dmckee 对 FSM 的(操作)定义以及它们如何应用于编程。
所以你有一个程序。 它有状态,而且状态的数量是有限的。 (“灯泡亮”或“灯泡暗”或“灯泡关”。3 种状态。有限。)您的程序一次只能处于一种状态。
因此,假设您希望程序改变状态。 通常,您会希望发生一些事情来触发状态更改。 在此示例中,我们如何根据用户输入来确定状态 - 例如按键。
您可能需要这样的逻辑。 当用户按下某个键时:
显然,您可能不是“更改灯泡”,而是“更改文本颜色”或程序需要执行的任何操作。 在开始之前,您需要定义您的状态。
所以看一些伪 C 代码:
并且,瞧。 一个改变状态的简单程序。
此代码仅执行
switch
语句的一小部分 - 取决于当前状态。 然后它更新该状态。 这就是 FSM 的工作原理。现在您可以执行以下操作:
显然,该程序只是更改了
currentState
变量。 您会希望您的代码在状态更改时执行更有趣的操作。 我不知道,doCoolBulbStuff()
函数实际上可能会将灯泡的图片显示在屏幕上。 或者其他什么。此代码仅查找按键。 但是您的 FSM(以及您的 switch 语句)可以根据用户输入的内容选择状态(例如,“O”表示“转到关闭”,而不是仅转到序列中的下一个。)
您提出的问题的一部分一个数据结构。
有人建议使用
enum
来跟踪状态。 这是我在示例中使用的#defines
的一个很好的替代方案。 人们也一直在建议使用数组——这些数组会跟踪状态之间的转换。 这也是一个很好用的结构。鉴于上述情况,您可以使用任何类型的结构(类似树的结构、数组等)来跟踪各个状态并定义在每个状态下执行的操作(因此一些建议使用“函数指针” “ - 有一个到函数指针的状态映射,指示在该状态下要做什么。)
希望有帮助!
The answers here seem really complex (but accurate, nonetheless.) So here are my thoughts.
First, I like dmckee's (operational) definition of an FSM and how they apply to programming.
So you have a program. It has states, and there is a finite number of them. ("the light bulb is bright" or "the light bulb is dim" or "the light bulb is off." 3 states. finite.) Your program can only be in one state at a time.
So, say you want your program to change states. Usually, you'll want something to happen to trigger a state change. In this example, how about we take user input to determine the state - say, a key press.
You might want logic like this. When the user presses a key:
Obviously, instead of "changing a bulb", you might be "changing the text color" or whatever it is you program needs to do. Before you start, you'll want to define your states.
So looking at some pseudoish C code:
And, voila. A simple program which changes the state.
This code executes only a small part of the
switch
statement - depending on the current state. Then it updates that state. That's how FSMs work.Now here are some things you can do:
Obviously, this program just changes the
currentState
variable. You'll want your code to do something more interesting on a state change. ThedoCoolBulbStuff()
function might, i dunno, actually put a picture of a lightbulb on a screen. Or something.This code only looks for a keypress. But your FSM (and thus your switch statement) can choose state based on what the user inputted (eg, "O" means "go to off" rather than just going to whatever is next in the sequence.)
Part of your question asked for a data structure.
One person suggested using an
enum
to keep track of states. This is a good alternative to the#defines
that I used in my example. People have also been suggesting arrays - and these arrays keep track of the transitions between states. This is also a fine structure to use.Given the above, well, you could use any sort of structure (something tree-like, an array, anything) to keep track of the individual states and define what to do in each state (hence some of the suggestions to use "function pointers" - have a state map to a function pointer which indicates what to do at that state.)
Hope that helps!
有关正式定义,请参阅维基百科。 您需要决定您的状态集 S、您的输入字母 Σ 和您的转换函数 δ。 最简单的表示是让 S 为整数 0, 1, 2, ..., N-1 的集合,其中 N 是状态数,对于 Σ 来说,是整数 0, 1, 2, ..., M-1 的集合,其中 M 是输入的数量,并且那么 δ 只是一个大的 N × M 矩阵。 最后,您可以通过存储 N 位数组来存储接受状态集,其中,如果第 i 位为 1,则第 i 位为 1。 state 是接受状态,如果不是接受状态则为 0。
例如,维基百科文章图 3 中的 FSM 如下:
See Wikipedia for the formal definition. You need to decide on your set of states S, your input alphabet Σ and your transition function δ. The simplest representation is to have S be the set of integers 0, 1, 2, ..., N-1, where N is the number of states, and for Σ be the set of integers 0, 1, 2, ..., M-1, where M is the number of inputs, and then δ is just a big N by M matrix. Finally, you can store the set of accepting states by storing an array of N bits, where the ith bit is 1 if the ith state is an accepting state, or 0 if it is not an accepting state.
For example, here is the FSM in Figure 3 of the Wikipedia article:
您基本上可以使用“if”条件和变量来存储 FSM 的当前状态。
例如(只是一个概念):
对于更复杂的实现,您可以考虑将状态转换存储在二维数组中:
You can basically use "if" conditional and a variable to store the current state of FSM.
For example (just a concept):
For more sophisticated implementation, you may consider store state transition in two dimension array:
来自 AT&T(现在在 Google)的几个人编写了可供通用使用的最好的 FSM 库之一。 在这里查看一下,它的名字是 OpenFST。
它快速、高效,并且他们创建了一组非常清晰的操作,您可以在 FSM 上执行这些操作,以执行诸如最小化它们或确定它们之类的操作,从而使它们对现实世界的问题更加有用。
A few guys from AT&T, now at Google, wrote one of the best FSM libraries available for general use. Check it out here, it's called OpenFST.
It's fast, efficient, and they created a very clear set of operations you can perform on the FSMs to do things like minimize them or determinize them to make them even more useful for real world problems.
如果 FSM 指的是有限状态机,
如果您喜欢简单,请使用枚举来命名您的状态
并在它们之间切换。
否则使用函子。 你可以看看
stl 或 boost 文档中的奇特定义。
它们或多或少是物体,具有
方法,例如调用 run(),执行
在那种状态下应该做的一切,
每个州都有自己的优势
范围。
if by FSM you mean finite state machine,
and you like it simple, use enums to name your states
and switch betweem them.
Otherwise use functors. you can look the
fancy definition up in the stl or boost docs.
They are more or less objects, that have a
method e.g. called run(), that executes
everything that should be done in that state,
with the advantage that each state has it's own
scope.
我们过去为电信公司实现了有限状态机,并且始终使用结构数组,预先填充如下:
我可能将函数指针
fn
声明为错误,因为它来自内存。 基本上,状态机在数组中搜索相关状态和事件,并调用执行必须执行的操作的函数,然后返回新状态。由于规则的优先级取决于它们在数组中的位置,因此特定状态放在最前面,ST_ANY 条目放在最后。 找到的第一个规则就是使用的规则。
此外,我记得我们对每个状态的第一个规则都有一个索引数组,以加快搜索速度(具有相同起始状态的所有规则都被分组)。
另请记住,这是纯 C 语言 - 很可能有更好的方法用 C++ 来实现。
We've implemented finite state machine for Telcos in the past and always used an array of structures, pre-populated like:
I may have the function pointer
fn
declared wrong since this is from memory. Basically the state machine searched the array for a relevant state and event and called the function which did what had to be done then returned the new state.The specific states were put first and the ST_ANY entries last since priority of the rules depended on their position in the array. The first rule that was found was the one used.
In addition, I remember we had an array of indexes to the first rule for each state to speed up the searches (all rules with the same starting state were grouped).
Also keep in mind that this was pure C - there may well be a better way to do it with C++.