方案中的有限状态机

时间:2011-05-25 19:27:54

标签: scheme racket

我正在尝试在Scheme中完成一个有限状态机。问题是,我不知道如何告诉它应该测试哪些字符。如果我想测试字符串“abc112”那么我该怎么做?

以下是代码:

#lang racket    
(define (chartest ch)
  (lambda (x) (char=? x ch)))
;; A transition is (list state char!boolean state)
(define fsmtrlst 
  (list
   (list 'start char-alphabetic? 'name)
   (list 'start char-numeric? 'number)
   (list 'start (chartest #\() 'lparen)
   (list 'start (chartest #\)) 'rparen)
   (list 'name char-alphabetic? 'name)
   (list 'name char-numeric? 'name)
   (list 'number char-numeric? 'number)))

(define (find-next-state state ch trl)
  (cond
    [(empty? trl) false]
    [(and (symbol=? state (first (first trl)))
          ((second (first trl)) ch))
     (third (first trl))]
    [else (find-next-state state ch (rest trl))]))

(define fsmfinal '(name number lparen rparen))

(define (run-fsm start trl final input)
  (cond
    [(empty? input)
     (cond
       [(member start final) true]
       [else false])]
    [else
     (local ((define next (find-next-state start (first input) trl)))
       (cond
         [(boolean? next) false]
         [else (run-fsm next trl final (rest input))]))]))

以下是我要测试的启动代码:

(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))

编辑:

好吧,..整体产品很好,但我的导师不满意,...他希望我制作一个具有过渡功能的有限状态机 - >类似于全局定义的东西会说:当处于状态X时,字符Y转到Z ...然后我将测试一个字符列表以查看它是假还是真...所以唯一的区别是代码不应该只使用数字和字母,而是任何字符......是否有可能?谢谢你的回答

编辑2:现在我有基本信息,它应该是什么样子:

也就是说,机器看起来像

A ---------> B ----------> C ----------> D ----------> (E)  字母数字字母

(define fsmtrlst
 (list
   (list 'A char-alphabetic? 'B)
   (list 'B char-numeric? 'C)
   (list 'C char-numeric? 'D)
   (list 'D char-alphabetic 'E)))

(define fsmfinal '(E))

(define fsmstart 'A)

但我不确定如何编写fsmstart的定义。

感谢您的回答。

这接受正好四个字符的序列,字母,数字,数字,字母等等。

编辑3:我正在使用在线教程和我的导师老师提供的一本书。我想出了我想制作的fsm。谢谢你的帮助。

出于好奇:

具有相当具体的fsm会有什么不同?

示例:

START ----“b”----->状态A -----“a”---->状态B -----“c”----->最终状态

只有当字符列表是“bac”而没有其他内容时,fsm才会成立。 有可能吗?

感谢您的反馈。

编辑4:

好的,我设法写了但又一次,我不知道如何输入字符。这是代码:

有3种状态,但只有从状态A进入状态C才会成立。

    (define (chartest ch)
    (lambda (x) (char=? x ch)))

    (define fsm-trans
       '((A, "a", B), (A, "b", A), (B, "c", C)))

    (define (find-next-state state ch trl)
      (cond
        [(empty? trl) false] 
        [(and (symbol=? state (first (first trl)))
              ((second (first trl)) ch)) <- And also this line returns an error
         (third (first trl))]
        [else (find-next-state state ch (rest trl))]))


    (define fsm-final '(C))

    (define start-state 'A)

    (define (run-fsm start trl final input)
      (cond
        [(empty? input)
         (cond
           [(member start final) true]
           [else false])]
        [else 
         (local ((define next (find-next-state start (first input) trl)))
           (cond
             [(boolean? next) false]
             [else (run-fsm next trl final (rest input))]))]))


    (run-fsm start-state fsm-trans fsm-final (list '("a", "c")))  <- I know this is the last problem with the code, the definition of the input. How can I tell Scheme what characters I want to test?

感谢您的回答!!!

1 个答案:

答案 0 :(得分:4)

我很好奇:我认为你没有写这个fsm?这是作业作业还是你想自学? FSM的代码看起来很好(事实上很好)。但是,你的发射线:

(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))

没有任何意义。原因如下:fsmtrlst是有限状态机转换列表。它是在第一个大代码块中定义的。 不是要调用的函数。我相信您要调用的函数是run-fsm。这需要一个开始符号,一个转换列表,一个最终状态列表和一个输入。输入实际上不是字符串,而是列表。因此,您可以使用以下行启动它:

(run-fsm 'start fsmtrlst fsmfinal (string->list "abc112"))

这将使用已定义的转换列表run-fsm,已定义的最终状态列表以及字符串“abc112”的输入就绪形式调用fsmtrlst

顺便说一句,除了'start之外的所有内容都被定义为最终(接受)状态。但是,并非所有输入都接受输入。例如,将“abc122”替换为“abc(122”,接受。

这是你想要的吗?

更新

您的编辑澄清了一些事情。您对fsmstart的定义很好。您确实在char-alphabetic?的{​​{1}}个fsmtrlst用法中错过了一个问号(?)。您是否不知道如何使用新定义?首先,您应删除fsmtrlstfsmfinal的旧定义。否则,您可能会遇到重复的定义错误。从您的新定义中,您要执行的行应如下所示:

(run-fsm fsmstart fsmtrlst fsmfinal (string->list "w00t"))

这将返回#t,因为“w00t”是一个后跟两个数字的字符,后跟一个字符。

我推测你仍然对方案的语法规则有困难,而不仅仅是你的特定程序的逻辑问题。您可能想尝试更简单的练习。

更新2:你不应该考虑制定一个新问题吗?

您最近的更新破坏了代码。 fsm的过渡部分起作用,因为过渡被定义为列表:

(from-state test-function to-state)

您试图创建转换:

(from-state string-literal to-state)

您可以将(A, "a", B)更改为(A (lambda (x) (string=? x "a") B)

当您尝试调用函数时,您使用了一个期望字符列表的函数,并为其提供了字符串列表的列表。这些都不是一回事。另外,你是否注意到你在你的列表中放了逗号,但它们在代码中没有其他地方存在?这些错误是我建议你开始一个方案教程的原因。这些是基本的计划问题,与您的特定练习无关。我建议你将你的编辑回溯到昨天的编辑。

不幸的是,我无法再更新此答案。我想更新我的答案,以便如果有人提出类似的问题,他们会看到一个完整的答案。但是,您提供了移动目标。请考虑暂停编辑并在有问题时提交新问题。