【问题标题】:Finite State Machine Simulation Implementation in ISL+ (Racket)ISL+(球拍)中的有限状态机仿真实现
【发布时间】:2018-10-30 18:43:17
【问题描述】:

我是一个通过 HTDP2(Felleisen 等人)独自工作的新手,但在第四章的问题 #380 上遇到了问题 - 交织数据。问题出在创建 DSL 的上下文中,但我首先重新熟悉了一个通用的 FSM 模拟器,并提供了以下代码:

; An FSM is a [List-of 1Transition]
; A 1Transition is a list of two items:
;   (cons FSM-State (cons FSM-State '()))
; An FSM-State is a String that specifies a color

; data examples 
(define fsm-traffic
  '(("red" "green") ("green" "yellow") ("yellow" "red")))

; FSM FSM-State -> FSM-State 
; matches the keys pressed by a player with the given FSM 
(define (simulate state0 transitions)
  (big-bang state0 ; FSM-State
    [to-draw
     (lambda (current)
      (overlay (text current 12 "black")
               (square 100 "solid" current)))]
[on-key
  (lambda (current key-event)
    (find transitions current))]))

; [X Y] [List-of [List X Y]] X -> Y
; finds the matching Y for the given X in alist
(define (find alist x)
  (local ((define fm (assoc x alist)))
    (if (cons? fm) (second fm) (error "not found"))))

那么问题陈述如下:

重新制定 1Transition 的数据定义,以便可以将转换限制为某些击键。尝试制定更改,以便find 继续工作而不进行更改。您还需要进行哪些更改才能使完整的程序正常运行?设计配方的哪一部分提供了答案?原始练习语句见练习 229。

练习 229 引入了结构类型定义来跟踪状态和转换,但由于问题陈述要求我保持在提供的 find 函数内,我很难想出类似的结构类型定义。相反,我提出了以下数据定义:

; An FSM is a [List-of Transition]
; A Transition is a two-item list of the following form:
; (cons FSM-State (cons (cons KeyEvent (cons FSM-State '()))'()))

; data example
(define fsm-traffic (list (list "red" (list "r" "green"))
                          (list "green" (list "g" "yellow"))
                          (list "yellow" (list "y" "red"))))

因此调用(find fsm-traffic "green") 我得到(list "g" "yellow") 因此我修改了on-key 子句如下:

(lambda (current key-event)
  (if (string=? key-event (first (first (rest (first transitions)))))
      (second (find transitions current))
      (error "invalid input")))

现在,如果我以 (simulate "red" fsm-traffic) 启动程序,则渲染 State0,如果我按“r”,它会进入“绿色”FSM 状态,但它不会接受“g”进入以下状态,所以开。

如果我以(simulate "yellow" fsm-traffic) 开始世界程序,则呈现 FSM 状态“黄色”但它不会转换到任何其他状态(error 子句被激活);同样以“绿色”作为起始状态。

我的预感是,由于我首先将 fsm-traffic 定义为“红色”状态,因此它接受其输入以转换为“绿色”,但由于其他状态没有发生同样的情况,big-bang 不是“杂耍” transitions 参数正确。但我只是不知道如何解决这个问题。我也不知道从我的数据定义开始我是否出错了。

提前感谢您帮助我。

P.D.请让我知道我是否遵守了在 stackoverflow 上发帖的规则(这是我的第一篇文章 :)。

【问题讨论】:

  • 顺便说一下,exercise 229 of the book 提供的数据定义与您的不同。虽然可以用任何一个来解决这个问题,但书中的数据定义可能更容易理解。你的“海市蜃楼”优势是你认为你可以使用assoc。但是,当状态既取决于当前状态又取决于关键事件时,您使用它的方式 assoc 就不够好。

标签: racket state-machine racket-student-languages


【解决方案1】:

您确定问题的根源是正确的。您首先使用"red" 状态和"r" 转换定义了fsm-traffic,而on-key 处理程序只查看first。它在if 问题中执行此操作:

(string=? key-event (first (first (rest (first transitions)))))
;                    ^                   ^
;                    |                   this makes it only look at `"red"`
;                    this makes it only look at `"r"` within that

这个if 的问题似乎很复杂。就像如果它是一个带有签名和目的的函数一样,我们可以设计这个表达式的输入、输出和目的。

输入:它应该依赖什么?

哪些键有效取决于转换表,但也取决于当前状态。这就是为什么只有"r""red" 状态下有效,而"g""green" 状态下有效。所以它的输入是:

current : FSM-State
key-event : KeyEvent
transitions : FSM

您现有的表达式会忽略current

输出和目的

这是一个if 问题,所以它应该输出一个Boolean。此布尔值的目的是确定密钥在当前状态下是否有效。

current 状态和key-event 的表中都有任何 转换时,它应该为真。

这个带有“any”和“both”的目的陈述听起来很复杂,它应该成为它自己的功能。使用我们刚刚制定的输入、输出和目的:

;; FSM-State KeyEvent FSM -> Boolean
;; Determines whether there is any transition in the FSM table for both the current
;; state and the key event.
(define (transition-for-state-and-key? state key table)
  ....)

您当前的正文表达式不包括state

(string=? key (first (first (rest (first table)))))

但实际的主体应该取决于statekey

就像这取决于两者一样,find 函数也应该同时取决于statekey

;; FSM-State KeyEvent FSM -> FSM-State
;; Finds the matching transition-state from the given state with the given key in the table.
(define (find-transition-state state key table)
  ....)

并注意transition-for-state-and-key?find-transition-state 之间的关系。当find-transition-state 不会出错时,transition-for-state-and-key? 函数应该返回 true。

这应该足以让您继续。

【讨论】:

    猜你喜欢
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 2011-03-31
    • 2017-01-04
    • 1970-01-01
    • 2018-11-13
    • 2014-01-09
    相关资源
    最近更新 更多