替换lisp中的元素

时间:2013-02-10 16:26:20

标签: function replace lisp common-lisp

我在Common Lisp中遇到了这个问题。 我需要操纵存在性变量来引入特殊规则。

例如,我需要建立一个转动的功能 (exist ?x (p ?x))中的(p sk00042)

sk00042是一个变量。请注意,当涉及通用变量时,此函数会变得有点困难。

例如,给定表达式(forall ?y (exist ?x (p ?x ?y))的函数将其转换为(forall ?y (p (sf666 ?y) ?y)。 这个想法是存在变量告诉我有一些东西满足公式。如果这个存在量词是外部的,那么这个量词不依赖于任何东西,上面第一个例子中的变量?x应该被这个函数生成的常量skoo42替换: (defun skolem-variable () (gentemp "SV-"))

如果更难(第二)的情况发生并存在一个存在主义的“out”的通用量词,那么存在的东西取决于普遍量化的变量,这意味着函数必须处理这种依赖性和通用变量变成了常数,就像在例子中一样:

(forall ?y (exist ?x (p ?x ?y)) ----> (forall ?y (p (sf666 ?y) ?y) 为此,还提供以下功能:

(defun skolem-function* (&rest args) (cons (gentemp "SF-") args))
(defun skolem-function (args) (apply #'skolem-function* args))

以下是一些更熟悉这个想法的例子:

(skolemize '(forall ?y (exist ?x (p ?x ?y))))
;=> (forall ?y (P (SF-1 ?Y) ?Y))
(skolemize '(exist ?y (forall ?x (p ?x ?y))))
;=> (for all ?x (P ?X SV-2)
(skolemize '(exist ?y (and (p ?x) (f ?y))))
;=> (AND (P ?X) (F SV-4))
(skolemize '(forall ?x (exist ?y (and (p ?x) (f ?y)))))
;=> (forall ?x (AND (P ?X) (F (SF-5 ?X)))

我需要构建给定的函数(使用上面的skolem-variableskolem-function) 表达式控制外部是否存在,然后用skolem-variable替换该变量。如果外部是一个后面并存在的forall,那么该功能就像我上面解释的那样。

1 个答案:

答案 0 :(得分:2)

我只是浏览了关于skolem普通形式的维基百科文章,但如果我做对了,每个存在主义都会成为一个skolem函数调用,其中绑定的通用作为参数(如果没有通用的范围,则为skolem常量)。一种简单的方法是在递归遍历表达式树时拥有一堆绑定的通用:

(defun skolemize (form &optional (universals nil))
  (cond ((null form) nil)                                  ; subtree done
        ((consp (car form))                                ; walk branches
         (cons (skolemize (car form) universals)
               (skolemize (cdr form) universals)))
        ((eq (car form) 'forall)                           ; universal binding
         (list 'forall
               (cadr form)
               (skolemize (caddr form)                     ; skolemize body
                          (cons (cadr form) universals)))) ; new var on the stack
        ((eq (car form) 'exist)                            ; existential binding
         (subst (if universals                             ; substitute variables
                    (cons (gentemp "SF-") universals)      ; with skolem function
                    (gentemp "SV-"))                       ; with skolem constant
                (cadr form)
                (skolemize (caddr form) universals)))
        (t (cons (car form) (skolemize (cdr form) universals)))))

请注意,这只是为了让您入门 - 我既没有深入研究这个主题,也没有真正针对性能或优雅进行测试或优化。此外,它将接受格式错误的输入,例如(skolemize '(forall (foo bar)))

您的示例:

CL-USER> (skolemize '(exist ?x (p ?x)))
(P SV-16)
CL-USER> (skolemize '(forall ?y (exist ?x (p ?x ?y))))
(FORALL ?Y (P (SF-17 ?Y) ?Y))
CL-USER> (skolemize '(exist ?y (forall ?x (p ?x ?y))))
(FORALL ?X (P ?X SV-18))
CL-USER> (skolemize '(exist ?y (and (p ?x) (f ?y))))
(AND (P ?X) (F SV-19))
CL-USER> (skolemize '(forall ?x (exist ?y (and (p ?x) (f ?y)))))
(FORALL ?X (AND (P ?X) (F (SF-20 ?X))))

测试更复杂的表达式:

CL-USER> (skolemize '(exist ?a
                      (forall ?b
                       (exist ?c
                        (forall ?d
                         (exist ?e (and (or (and (f ?a) (g ?b))
                                            (and (f ?c) (g ?d)))
                                        (or (and (f ?c) (g ?e))
                                            (and (f ?d) (g ?e))))))))))
(FORALL ?B
  (FORALL ?D (AND (OR (AND (F SV-15) (G ?B))
                      (AND (F (SF-16 ?B)) (G ?D)))
                  (OR (AND (F (SF-16 ?B)) (G (SF-17 ?D ?B)))
                      (AND (F ?D) (G (SF-17 ?D ?B)))))))