探索FSM (有限状态机)应用
有限状态机(FSM) 是计算机科学中的一种数学模型,可用于表示和控制系统的行为。它由一组状态以及定义在这些状态上的转换函数组成。FSM 被广泛用于计算机程序中的状态机制。
有限状态机(FSM)应用场景
-
在各种自动化系统的应用: 例如交通信号灯、地铁站的旋转闸门、银行自动取款机等。通过对状态和转换函数的定义,可以实现对系统行为的精确控制。
交通信号灯状态流转图
地铁站的旋转闸门状态流转图
银行自动取款机状态流转图
-
在编程领域的应用: 例如在编写编译器和解释器时,可以使用有限状态机(FSM) 来处理词法分析。例如:
JSON.Parse
-
在Notion中应用: 可以使用 有限状态机(FSM) 的相关概念来构建各种工作流程,例如状态转换图、状态转换表等。
-
在web中应用: 我们熟悉的 Promise 也是一个状态机,具有三个状态:pending、resolved。rejected。
Promise状态流转图
登录功能流转图
类似这样的状态机的例子数不胜数,甚至于,人也是一种极其复杂的状态机,给定一种刺激或多种刺激组合,也会触发人从某种状态过渡到另一种状态。只不过复杂程度极高,以至于现代科学完全无法解密这种状态机。
有限状态机(FSM)实现原理
具体来说,FSM由以下几部分组成:
- 初始状态:系统的初始状态。
- 状态集合:表示系统可能处于的各种状态。
- 转移函数:定义系统在不同状态之间的转移条件和结果。
- 终止状态:系统在某个状态下可以停止计算。
有限状态机(FSM) 的实现基于状态转移图。状态转移图 是一个有向图,它表示有限状态机(FSM) 中状态之间的转移关系。在状态转移图中,每个状态表示系统的某种状态,每个转移表示系统从一个状态转移到另一个状态的条件和结果。
实现简易的有限状态机(FSM)
实现步骤
- 当状态机开始执行时,它会自动进入初始化状态(initial state)。
- 每个状态都可以定义,在进入(onEnter)或退出(onExit)该状态时发生的行为事件(actions),通常这些行为事件会携带副作用(side effect)。
- 每个状态都可以定义触发转换(transition)的事件。
- 转换定义了在退出一个状态并进入另一个状态时,状态机该如何处理这种事件。
- 在状态转换发生时,可以定义可以触发的行为事件,从而一般用来表达其副作用。
状态转移图
function createMachine(stateMachineDefinition) {const machine = {value: stateMachineDefinition.initialState,performTransition(currentState, event) {const currentStateDefinition = stateMachineDefinition[currentState];const destinationTransition = currentStateDefinition.transitions[event];if (!destinationTransition) {return;}const destinationState = destinationTransition.target;const destinationStateDefinition =stateMachineDefinition[destinationState];destinationTransition.action();currentStateDefinition.actions.onExit();destinationStateDefinition.actions.onEnter();machine.value = destinationState;return machine.value;},};return machine;
}const machine = createMachine({initialState: "off",off: {actions: {onEnter() {console.log("off: onEnter");},onExit() {console.log("off: onExit");},},transitions: {switch: {target: "on",action() {console.log('transition action for "switch" in "off" state');},},},},on: {actions: {onEnter() {console.log("on: onEnter");},onExit() {console.log("on: onExit");},},transitions: {switch: {target: "off",action() {console.log('transition action for "switch" in "on" state');},},},},
});let state = machine.value;
console.log(`current state: ${state}`);
state = machine.performTransition(state, "switch");
console.log(`current state: ${state}`);
state = machine.performTransition(state, "switch");
console.log(`current state: ${state}`);
有限状态机(FSM)的 应用实现
在状态比较多的情况下,把状态、事件及 transitions 集中到一个状态机中,进行统一管理。这样不需要写太多的 if-else,或者 case 判断,如果增加状态和事件,也便于代码的维护和扩展。
文本解析器
实现思路
- 确定状态和输入
在编写 FSM 之前,我们需要确定我们的状态和输入。在这个例子中,我们将定义三个状态:起始状态、数字状态和字符串状态。我们还将定义四个输入:数字、字母、引号和空格。 - 定义状态机类
现在,我们可以编写代码来实现我们的 FSM 。我们需要定义一个状态机类,它将接受输入,并根据转移规则转换状态。该类应该包含以下属性:currentState
:当前状态。states
:状态列表。transitions
:转移列表。
它还应该包含以下方法:transition
:该方法接受一个输入参数input
,根据当前状态以及输入参数,执行相应的状态转换。
- 定义转移规则
我们还需要定义状态之间的转移规则。为此,我们将使用转移列表,其中包含状态之间的映射和输入。转移规则应该考虑当前状态和输入,并根据它们确定下一个状态。如果当前状态和输入没有匹配的转移规则,则应该抛出一个异常。 - 解析文本
现在,我们可以使用状态机解析文本。我们需要将文本拆分为单词,并将每个单词作为输入提供给状态机。在处理完所有输入后,我们可以通过调用getInputType
方法来获取解析的令牌。
示例代码
const STATES = {START: "start",NUMBER: "number",STRING: "string",
};const INPUTS = {NUMBER: "number",LETTER: "letter",SPACE: "space",QUOTE: "quote",
};const TRANSITIONS = [{currentState: STATES.START,input: INPUTS.NUMBER,nextState: STATES.NUMBER,},{currentState: STATES.START,input: INPUTS.LETTER,nextState: STATES.STRING,},{ currentState: STATES.START, input: INPUTS.SPACE, nextState: STATES.START },{ currentState: STATES.START, input: INPUTS.QUOTE, nextState: STATES.STRING },{currentState: STATES.NUMBER,input: INPUTS.NUMBER,nextState: STATES.NUMBER,},{ currentState: STATES.NUMBER, input: INPUTS.SPACE, nextState: STATES.START },{currentState: STATES.STRING,input: INPUTS.LETTER,nextState: STATES.STRING,},{ currentState: STATES.STRING, input: INPUTS.SPACE, nextState: STATES.START },{ currentState: STATES.STRING, input: INPUTS.QUOTE, nextState: STATES.START },
];class TextParse {constructor() {this.currentState = STATES.START;this.buffer = "";this.type;}performTransition(input) {const transition = TRANSITIONS.find((t) => t.currentState === this.currentState && t.input === input.type);if (!transition)throw new Error(`Invalid input "${input.value}" for state "${this.currentState}"`);this.currentState = transition.nextState;if (this.currentState === STATES.START) {const token = this.buffer;const type = this.type;this.buffer = "";this.type = "";return {type,value: token,};} else {this.buffer += input.value;this.type = input.type;}}
}function textParse(input) {const textParse = new TextParse();const tokens = [];for (let i = 0; i < input.length; i++) {const char = input[i];try {const token = textParse.performTransition({type: getInputType(char),value: char,});if (token) {tokens.push(token);}} catch (e) {console.error(e.message);return null;}}const lastToken = textParse.performTransition({ type: INPUTS.SPACE });if (lastToken) {tokens.push(lastToken);}return tokens;
}function getInputType(char) {if (/[0-9]/.test(char)) {return INPUTS.NUMBER;} else if (/[a-zA-Z]/.test(char)) {return INPUTS.LETTER;} else if (/[\s\n\t\r]/.test(char)) {return INPUTS.SPACE;} else if (char === '"') {return INPUTS.QUOTE;} else {throw new Error(`Unknown input type for "${char}"`);}
}// Example usage:
console.log(textParse('123 abc "def ghi" 456'));
// [
// { type: 'number', value: '123' },
// { type: 'letter', value: 'abc' },
// { type: 'letter', value: '"def' },
// { type: 'letter', value: 'ghi' },
// { type: '', value: '' },
// { type: 'number', value: '456' }
// ]
示例代码
web 应用
使用 有限状态机(FSM) 结合 React 构建 web 应用,不局限于身份认证,登录,步骤表单,有蛮多 web 应用在
有限状态机(FSM)的实践 ,下面主要描述 从有限状态机(FSM)在服务端拉取数据的状态转移上的应用
-
状态转移图
-
状态集(States), 转换规则(Transitions)
const states = {INITIAL: "idle",LOADING: "loading",SUCCESS: "success",FAILURE: "failure",
};
const transitions = {[states.INITIAL]: {fetch: () => /* Returns states.LOADING */,},[states.LOADING]: {},[states.SUCCESS]: {reload: () => /* Returns states.LOADING */,clear: () => /* Returns states.INITIAL */,},[states.FAILURE]: {retry: () => /* Returns states.LOADING */,clear: () => /* Returns states.INITIAL */,},
}
示例代码
总结
结合前端应用的探索体现的不多,可以再作为第二篇内容去探讨,有兴趣的同学可以尝试一下 有限状态机(FSM) 在 web 上的应用探索,以及 Xstate库(FSM封装的功能性库) 的应用,以及跟 状态管理库 差异化的知识。在这里提醒一点,状态管理库 (Redux) 和 Xstate 并不是互斥的,Xstate 关注的是如何设计状态,状态管理库关注的是如何管理状态。事实上,状态机几乎可以与任何无主见的状态管理工具一起使用。我鼓励您探索各种方法,以确定最适合您、您的团队和您的应用程序的方法。
相关文章:

探索FSM (有限状态机)应用
有限状态机(FSM) 是计算机科学中的一种数学模型,可用于表示和控制系统的行为。它由一组状态以及定义在这些状态上的转换函数组成。FSM 被广泛用于计算机程序中的状态机制。 有限状态机(FSM)应用场景 在各种自动化系统…...
6.continue break
6.1continue 关键字 continue 关键字用于立即跳出本次循环,继续下一次循环(本次循环体continue之后的代码会少执行一次)。 例如:吃5个包子,第3个有虫子,就扔掉第3个包子,继续吃第4个第5个包子…...
如何在Linux中强制关闭卡住的PyCharm
在使用PyCharm进行Python开发时,有时可能会遇到卡顿或无响应的情况。当PyCharm卡住时,我们需要强制关闭它以恢复正常操作。今天,我们将介绍在Linux系统中如何强制关闭PyCharm的几种方法。 1. 使用键盘快捷键 在PyCharm所在的窗口中…...
c# Excel数据的导出与导入
搬运:Datagrideview 数据导出Excel , Exel数据导入 //------------------------------------------------------------------------------------- // All Rights Reserved , Copyright (C) 2013 , DZD , Ltd . //----------------------------------------------------------…...

Kotlin~Mediator中介者模式
概念 创建一个中介来降低对象之间的耦合度,关系”多对多“变为“一对多”。 角色介绍 Mediator:抽象中介者,接口或者抽象类。ConcreteMediator:中介者具体实现,实现中介者接口,定义一个List管理Colleagu…...
石子合并问题
一.试题 在一个园形操场的四周摆放N堆石子(N≤100),现要将石子有次序地合并成一堆。规定 每次只能选相邻的两堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。 编一程序,由文件读入…...
剑指Offer-搜索与回溯算法
文章目录 剑指 Offer 32 - I. 从上到下打印二叉树题意:解:代码: 剑指 Offer 32 - II. 从上到下打印二叉树 II题意:解:代码: 剑指 Offer 32 - III. 从上到下打印二叉树 III题意:解:代…...

【云原生】Docker 详解(三):Docker 镜像管理基础
Docker 详解(三):Docker 镜像管理基础 1.镜像的概念 镜像可以理解为应用程序的集装箱,而 Docker 用来装卸集装箱。 Docker 镜像含有启动容器所需要的文件系统及其内容,因此,其用于创建并启动容器。 Dock…...

SD-MTSP:蜘蛛蜂优化算法SWO求解单仓库多旅行商问题MATLAB(可更改数据集,旅行商的数量和起点)
一、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法(Spider wasp optimizer,SWO)由Mohamed Abdel-Basset等人于2023年提出,该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为,具有搜索速度快,求解精度高的优势。蜘蛛蜂优化算…...
【ARM 嵌入式 编译系列 3.1 -- GCC __attribute__((used)) 使用】
文章目录 __attribute__((used)) 属性介绍代码演示编译与输出GCC 编译选项 上篇文章:ARM 嵌入式 编译系列 3 – GCC attribute((weak)) 弱符号使用 下篇文章:ARM 嵌入式 编译系列 3.2 – glibc 学习 __attribute__((used)) 属性介绍 在普通的 C/C 程序中…...

C++ ModBUS TCP客户端工具 qModMaster 介绍及使用
qModMaster工具介绍 QModMaster是一个基于Qt的Modbus主站(Master)模拟器,用于模拟和测试Modbus TCP和RTU通信。它提供了一个直观的图形界面,使用户能够轻松设置和发送Modbus请求,并查看和分析响应数据。 以下是QModM…...

笔记本电脑如何把sd卡数据恢复
在使用笔记本电脑过程中,如果不小心将SD卡里面的重要数据弄丢怎么办呢?别着急,本文将向您介绍SD卡数据丢失常见原因和恢复方法。 ▌一、SD卡数据丢失常见原因 - 意外删除:误操作或不小心将文件或文件夹删除。 - 误格式化&#…...

【2023 华数杯全国大学生数学建模竞赛】 B题 不透明制品最优配色方案设计 39页论文及python代码
【2023 华数杯全国大学生数学建模竞赛】 B题 不透明制品最优配色方案设计 39页论文及python代码 1 题目 B 题 不透明制品最优配色方案设计 日常生活中五彩缤纷的不透明有色制品是由着色剂染色而成。因此,不透明制品的配色对其外观美观度和市场竞争力起着重要作用。…...

Exams/ece241 2013 q4
蓄水池问题 S3 S2 S1 例如:000 代表 无水 ,需要使FR3, FR2, FR1 都打开(111) S3 S2 S1 FR3 FR2 FR1 000 111 001 011 011 001 111 000 fr代表水变深为…...

Android OkHttp源码分析--分发器
OkHttp是当下Android使用最频繁的网络请求框架,由Square公司开源。Google在Android4.4以后开始将源码中 的HttpURLConnection底层实现替换为OKHttp,同时现在流行的Retrofit框架底层同样是使用OKHttp的。 OKHttp优点: 1、支持Http1、Http2、Quic以及Web…...

大数据面试题:说下Spark中的Transform和Action,为什么Spark要把操作分为Transform和Action?
面试题来源: 《大数据面试题 V4.0》 大数据面试题V3.0,523道题,679页,46w字 可回答:Spark常见的算子介绍一下 参考答案: 我们先来看下Spark算子的作用: 下图描述了Spark在运行转换中通过算…...

【图像去噪的扩散滤波】基于线性扩散滤波、边缘增强线性和非线性各向异性滤波的图像去噪研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
python函数、运算符等简单介绍2(无顺序)
list(列表) 列表是Python的一种内置数据类型,列表是可以装各种数据类 型的容器 # 第一种list创建方式 list_name [晓东,小刚,明明,小红,123,123.4,123] print(list_name) print(type(list_name)) # 输出结果: [晓东, 小刚, 明明…...
k8s 自身原理 3
前面有分享到 master 主节点上的 四个组件,etcd,ApiServer,scheduler,controller manager 接下来我们分享一波 woker 节点上的组件,xdm 还记得 worker 节点上都有什么吗? kubeletkube-proxy实际的服务对应…...

SpringBoot 3自带的 HTTP 客户端工具
原理 Spring的HTTP 服务接口是一个带有HttpExchange方法的 Java 接口,它支持的支持的注解类型有: HttpExchange:是用于指定 HTTP 端点的通用注释。在接口级别使用时,它适用于所有方法。GetExchange:为 HTTP GET请求指…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...

边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...