SCXML有限状态自动机

状态机简介

状态存储关于过去的信息,就是说:它反映从系统开始到现在时刻的输入变化。转移指示状态变更,并且用必须满足来确使转移发生的条件来描述它。动作是在给定时刻要进行的活动的描述。有多种类型的动作:

进入动作(entry action):在进入状态时进行
退出动作:在退出状态时进行
输入动作:依赖于当前状态和输入条件进行
转移动作:在进行特定转移时进行

    FSM(有限状态机)可以使用上面图 1 那样的状态图(或状态转移图)来表示。此外可以使用多种类型的状态转移表。下面展示最常见的表示:当前状态(B)和条件(Y)的组合指示出下一个状态(C)。完整的动作信息可以只使用脚注来增加。包括完整动作信息的
FSM 定义可以使用状态表

State
Chart XML (SCXML): State Machine Notation for Control Abstraction

  • SCXML Parser
  • 核心 API,用于 SCXML 文档的解析模块,该 SCXML 文档中的各个元素解析组装成对应的 Java 对象实现。
  • DataModel
  • 核心 API,用于实现 SCXML 状态机中的数据模型定义,将 SCXML 文档中的 datamodel 元素对应的子元素封装成 Java 对象,供状态机引挚在后续操作中使用。
  • Context and Evaluators
  • 核心 API,用于实现对 SCXML 状态机中上下文环境的保存和更改,以及对 SCXML 文档中表达式语言(例如 <log expr=”${data.value}” />)的解析操作。
  • Executor
  • 引挚执行器的实例化模块,核心 API,通过此模块完成一个完整引挚执行器的组装和实例化,并提供引挚启动,停止服务器基础功能模块。
  • Triggering Event
  • 核心 API,SCXML 引挚中事件的定义实现和执行模块。此模块完成一个外部事件的封装,事件池的组织以及具体的事件作用流程控制。
  • Custom Actions
  • 高级 API,SCXML 状态机引挚的自定义事件支持。除了 SCXML 标准自带的 <var >、<assign> 和 <log> 等标准事件外,程序人员可以进行自定义事件的开发工作,例如系统平台的构件添加、构件删除操作等,需要程序人员的扩展开发工作。以下代码为 Custom Actions 的使用范例。

应用场景:

    

应用案例说明:

计时器的例子:

创建Maven工程:

<dependencies>    <dependency>        <groupId>commons-scxml</groupId>        <artifactId>commons-scxml</artifactId>        <version>0.9</version>    </dependency>

<dependency>        <groupId>commons-jexl</groupId>        <artifactId>commons-jexl</artifactId>        <version>1.1</version>    </dependency>

<dependency>        <groupId>xalan</groupId>        <artifactId>xalan</artifactId>        <version>2.6.0</version>    </dependency>

</dependencies>

创建状态机模型文件:stopwatch.xml

<scxml xmlns="http://www.w3.org/2005/07/scxml"       version="1.0"       initialstate="reset">    <state id="reset">        <transition event="watch.start"   target="running"/>    </state>    <state id="running">        <transition event="watch.split"   target="paused"/>        <transition event="watch.stop"    target="stopped"/>    </state>    <state id="paused">        <transition event="watch.unsplit" target="running"/>        <transition event="watch.stop"    target="stopped"/>    </state>    <state id="stopped">        <transition event="watch.reset"   target="reset"/>    </state></scxml>

创建状态机:StopWatch.java

import org.apache.commons.scxml.SCXMLListener;import org.apache.commons.scxml.env.AbstractStateMachine;import org.apache.commons.scxml.model.ModelException;import org.apache.commons.scxml.model.State;import org.apache.commons.scxml.model.Transition;import org.apache.commons.scxml.model.TransitionTarget;

import java.util.Timer;import java.util.TimerTask;

public class StopWatch extends AbstractStateMachine {/**     * The events for the stop watch.     */    public static final String EVENT_START = "watch.start",            EVENT_STOP = "watch.stop", EVENT_SPLIT = "watch.split",            EVENT_UNSPLIT = "watch.unsplit", EVENT_RESET = "watch.reset";

/**     * The fragments of the elapsed time.     */    private int hr, min, sec, fract;

/**     * The fragments of the display time.     */    private int dhr, dmin, dsec, dfract;

/**     * The stopwatch "split" (display freeze).     */    private boolean split;

/**     * The Timer to keep time.     */    private Timer timer;

/**     * The display decorations.     */    private static final String DELIM = ":", DOT = ".", EMPTY = "", ZERO = "0";

public StopWatch() throws ModelException {

super(StopWatch.class.getClassLoader().getResource("stopwatch.xml"));        getEngine().addListener(getEngine().getStateMachine(), new EntryListener());        System.out.println(StopWatch.class.getClassLoader().getResource("stopwatch.xml"));    }

public void reset() {

hr = min = sec = fract = dhr = dmin = dsec = dfract = 0;        split = false;    }

public void running() {

split = false;        if (timer == null) {timer = new Timer(true);            timer.scheduleAtFixedRate(new TimerTask() {@Override                public void run() {                    increment();                }            }, 100, 100);        }    }

public void paused() {

split = true;    }

public void stopped() {

timer.cancel();        timer = null;    }

public String getDisplay() {

String padhr = dhr > 9 ? EMPTY : ZERO;        String padmin = dmin > 9 ? EMPTY : ZERO;        String padsec = dsec > 9 ? EMPTY : ZERO;        return new StringBuffer().append(padhr).append(dhr).append(DELIM).                append(padmin).append(dmin).append(DELIM).append(padsec).                append(dsec).append(DOT).append(dfract).toString();    }

public String getCurrentState() {

return ((State)getEngine().getCurrentStatus().getStates().iterator().next()).getId();    }

private void increment() {if (fract < 9) {fract++;        } else {fract = 0;            if (sec < 59) {sec++;            } else {sec = 0;                if (min < 59) {min++;                } else {min = 0;                    if (hr < 99) {hr++;                    } else {hr = 0; //wrap                    }                }            }        }if (!split) {dhr = hr;            dmin = min;            dsec = sec;            dfract = fract;        }    }

/**     * A SCXMLListener that is only concerned about &quot;onentry&quot;     * notifications.     */    protected class EntryListener implements SCXMLListener {public void onEntry(final TransitionTarget entered) {            System.out.println("Current State:"+entered.getId());        }public void onTransition(final TransitionTarget from,                                 final TransitionTarget to, final Transition transition) {// nothing to do        }public void onExit(final TransitionTarget exited) {// nothing to do        }

}}

测试代码:

public static void main(String[] args) throws ModelException {

StopWatch stopWatch = new StopWatch();    Scanner input=new Scanner(System.in);    System.out.println("event: watch.start watch.stop watch.reset watch.split watch.unsplit");    while(true){        String event=input.nextLine();        if(event.trim()!=null&&!event.trim().equals("")){if(event.equals("exit")) break;            else{                stopWatch.fireEvent(event);                System.out.println(stopWatch.getCurrentState());                System.out.print(stopWatch.getDisplay());            }        }    }

}

每一个状态下会调用对应状态的方法来处理具体的业务处理逻辑。这样就可以实现一个简单的处理机。

Q&A:

关于序列化:2.0版本中可以通过将SCXML中attach的SCInstance实例的序列化来完成,恢复后通过deattach来恢复。

状态恢复:可以通过引入一个新的状态reset状态

reference:

http://www.ibm.com/developerworks/cn/opensource/os-cn-scxml/

http://www.w3.org/TR/scxml/

http://commons.apache.org/proper/commons-scxml/faq.html

时间: 2024-10-01 12:34:58

SCXML有限状态自动机的相关文章

人工智能,有限状态自动机-小游戏的自动学习

问题描述 有空编了一个贪吃蛇游戏,成功是成功了.但是想让游戏自动走,以学习如何才能高效的吃到食物.食物可能是青蛙等,会躲避动作.贪吃蛇的走法只有四个方向,个人觉得用有限状态自动机来实现,但是不懂得其原因.请大侠们指导一下.谢谢!!!本游戏,蛇有视觉,会记录看到的东西,并自动攻击. 解决方案 解决方案二:新手就别一下想太多了你先把青蛙如何能够自动躲避做出来再说解决方案三:1.首先蛇和青蛙得有个速度比如每次一格每次二格.速度可以不同2.蛇的视野范围是多大,青蛙视野范围多大3.路线最优算法.配合障碍.

Aho-Corasick 多模式匹配算法、AC自动机详解

Aho-Corasick算法是多模式匹配中的经典算法,目前在实际应用中较多. Aho-Corasick算法对应的数据结构是Aho-Corasick自动机,简称AC自动机. 搞编程的一般都应该知道自动机FA吧,具体细分为:确定性有限状态自动机(DFA)和非确定性有限状态自动机NFA.普通的自动机不能进行多模式匹配,AC自动机增加了失败转移,转移到已经输入成功的文本的后缀,来实现. 1.多模式匹配 多模式匹配就是有多个模式串P1,P2,P3...,Pm,求出所有这些模式串在连续文本T1....n中的

正则表达式及其他

正则 什么是正则表达式呢?正则表达式实际上是一个主要用来描述字符串匹配的工具,当然也可以用来匹配其它的东西例如二进制数据,用在字符串方面可能是最常见的.说到这里,可能大家会联想到如下几个主题:怎么排除恶意的脚本代码?要写一个脚本语言引擎或者编译器,是否可以用正则表达式来完成?编译原理? 实际上要说清楚这里面的所有问题也许已经超出了我的能力范围了,但是我还是要写下来,再不写下来也许哪天我就真的忘得一干二净了. 首先说正则表达式吧.正则表达式实际上使用的是一个不确定有穷自动机,Non-determi

Regular Expression 正则表达式-1 (C#)

express|正则 起因是因为一片帖子,问到了一个问题,帖子是这样的: Originally Posted by 人就是这样我想编一个程序,但学CompSci是很久以前的事情了.想请教请教大家. 有两个txt文件,一个叫source.txt(有很多数据), 一个叫target.txt(空白的) 我想把source.txt里的一些数据提取出来(稍微修改一下),然后写到target.txt里面. 举个例子:sourse.txt里的数据:2oi)4@##( "data:001%abc"&g

java正则表达式彻底研究_正则表达式

 package testreg; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * <p>Title: 正则表达式的研究</p> * <p>Description: * 最近在工作中常常用到一些正则表达式的使用问题,到网上去找介绍大多是一鳞半爪.求人不如 * 求已.一狠心,自己看!这两天利用我们项目两期之间的一点空闲对J2SE所支持的正则表达式来 * 了个彻底研究!代价是--就是

编译原理

编译原理 语法是指这样的一组规则,用它可以形成和产生一个合适的程序. 词法规则是指单词符号的形成规则. 语法规则是语法单位的形成规则,规定了如何从单词符号形成更大的结构(即语法单位或语法范畴). 一般程序语言的语法单位有:表达式.语句.分程序.函数.过程和程序等. 程序语言的基本功能是描述数据和对数据的运算.所谓程序,从本质上来说是描述一定数据的处理过程.   强制式语言也称过程式语言.其特点是命令驱动,面向语句.一个强制式语言程序由一系列的语句组成,每个语句的执行引起若干存储单元中的值的改变.

抽象的艺术 - 状态机

道林.格雷 : "你喜欢什么类型的音乐 What sort of music would you like?" 温妮莎·艾芙斯 : "看这一刻我想成为什么样的人 Meaning who do I want to be at this moment." FSM 有限状态机 Finite State Machine,又称有限状态自动机Finite State Automaton,又称有限自动机Finite Automaton,简称状态机 State Machine.简单

策略模式的孪生兄弟——对状态模式的深度复习总结

俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!涉及的总结知识点如下: 和策略模式的比较 状态模式概念和例子 应用场景 责任链模式和状态模式对比 一种代码优化的思路 java.util.Iterator里也有状态模式的影子 状态模式的优缺点 有限状态机及其应用 前面有总结--策略模式,之前早就觉得策略和状态设计模式有一些相似-- 接口的常用用法都有什么?策略设计模式复习总结 我知道策略模式是对象的行为模式,其实就是对一系列级别平等的算法的封装,它不关心算法实现,让客户端去动态的

Linux内核剖析 之 内核同步

主要内容     1.内核请求何时以交错(interleave)的方式执行以及交错程度如何.     2.内核所实现的基本同步机制.     3.通常情况下如何使用内核提供的同步机制. 内核如何为不同的请求服务     哪些服务?     ====>>>     为了更好地理解内核是如何执行的,我们把内核看做必须满足两种请求的侍者:一种请求来自顾客,另一种请求来自数量有限的几个不同的老板.对于不同的请求,侍者采用如下的策略:     1.老板提出请求时,如果侍者空闲,则侍者开始为老板服务