Emacs LISP-DeMorgan';列出清单

Emacs LISP-DeMorgan';列出清单,emacs,lisp,demorgans-law,Emacs,Lisp,Demorgans Law,我在上人工智能课程,我们有一个程序要写。这个程序显然很简单,所有其他学生都是用java编写的。然而,我知道它可以在LISP中用更少的工作来完成。好。少打字。但是我已经读了一周关于LISP的书,我对它感到惊讶。我决心学习更多,并且使用LISP不仅仅是为了这个课程。我今年23岁,正在学习一门1958年形成的语言。有点浪漫。我很高兴能像躲避瘟疫一样避开我的鼠标垫 他举的例子说明了整个程序。他注意到他使用递归,而不是prog。至少我明白这意味着什么 (rewrite '(or a (and b (not

我在上人工智能课程,我们有一个程序要写。这个程序显然很简单,所有其他学生都是用java编写的。然而,我知道它可以在LISP中用更少的工作来完成。好。少打字。但是我已经读了一周关于LISP的书,我对它感到惊讶。我决心学习更多,并且使用LISP不仅仅是为了这个课程。我今年23岁,正在学习一门1958年形成的语言。有点浪漫。我很高兴能像躲避瘟疫一样避开我的鼠标垫

他举的例子说明了整个程序。他注意到他使用递归,而不是prog。至少我明白这意味着什么

(rewrite '(or a (and b (not (or c d)))))

--> (OR A (AND B (AND (NOT C) (NOT D))))

(rewrite '(and a (or b (not (and c (and d e))))))

--> (AND A (OR B (NOT C) (OR (NOT D) (NOT E)))))
我理解德摩根定律。我只是不知道该怎么处理这件事!到目前为止我所拥有的是。。。令人尴尬的我的笔记本上写满了我试图把这些画出来的几页。我将对最简单的情况进行最接近的尝试,即:

(not (or a b))
我想如果我能处理好这件事,剩下的我就可以处理了。大概我做了一个叫做boom的函数,上面的语句就是我所说的boomable列表

(defun boom (sexp)

  (let ((op (car (car (cdr sexp)))) 

    (operands (cdr (car (cdr sexp))))))

  (if (equal op 'and)

      (setcar sexp 'or)

    (setcar sexp 'and))

  (print operands)

  (print sexp))

                ;end boom
我在最后打印以进行调试。 对列表操作数的更改并不反映原始sexp中的更改(对我来说,这是一个巨大的损失)


告诉我我的东西是假的,并指导我。

写一个快速而肮脏的版本并不难。您只需要检查公式是原始命题变量(在本例中为原子)、二进制连接词还是否定词。如果它是否定的,那么你需要处理内部

(defun demorganify (formula)
  (if (atom formula)
      formula
    (let ((operator (first formula)))
      (case operator
        ((and or)
         (list* operator (mapcar 'demorganify (rest formula))))
        ((not)
         (let ((subformula (second formula)))
           (if (atom subformula)
               formula
             (let* ((suboperator (first subformula))
                    (new-suboperator (case suboperator
                                       ((not) 'not)
                                       ((and) 'or)
                                       ((or) 'and)))
                    (demorganify-and-negate (lambda (f)
                                              (demorganify (list 'not (demorganify f))))))
               (list* new-suboperator (mapcar demorganify-and-negate (rest subformula)))))))))))

不过,这当然可以更简洁一些。

这两个函数应该将
而不是
分配到括号中:

(defun de-morgan (formula)
  (if (listp formula)
      (let ((op (first formula)))
        (case op
          (and `(and ,(de-morgan (second formula)) ,(de-morgan (third formula))))
          (or `(or ,(de-morgan (second formula)) ,(de-morgan (third formula))))
          (not (de-morgan-negate (second formula)))))
    formula))

(defun de-morgan-negate (formula)
  (if (listp formula)
      (let ((op (first formula)))
        (case op
          (and `(or ,(de-morgan-negate (second formula)) ,(de-morgan-negate (third formula))))
          (or `(and ,(de-morgan-negate (second formula)) ,(de-morgan-negate (third formula))))
          (not (de-morgan (second formula)))))
    `(not ,formula)))



(de-morgan 'a)
(de-morgan '(not a))
(de-morgan '(not (not a)))
(de-morgan '(and a b))
(de-morgan '(not (and a b)))
(de-morgan '(not (or a b)))
(de-morgan '(not (and (and (not a) b) (not (or (not c) (not (not d)))))))

通用Lisp,无需简化:

(defun de-morgan (exp)
  (cond ;; atom
        ((atom exp) exp)
        ;; (not (and p q))  or  (not (or p q))
        ((and (consp exp)
              (equal (car exp) 'not)
              (consp (cadr exp))
              (or (equal (caadr exp) 'and)
                  (equal (caadr exp) 'or)))
         (list (case (caadr exp)
                 (and 'or)
                 (or 'and))
               (de-morgan (list 'not (car  (cdadr exp))))
               (de-morgan (list 'not (cadr (cdadr exp))))))
        ;; otherwise some other expression
        (t (cons (car exp) (mapcar #'de-morgan (rest exp))))))

基于通用Lisp解决方案,使用模式匹配的Emacs Lisp解决方案:

(defun de-morgan (exp)
  (pcase exp
    ((pred atom) exp)
    (`(not (and ,a ,b)) `(or ,(de-morgan `(not ,a))
                             ,(de-morgan `(not ,b))))
    (`(not (or ,a ,b)) `(and ,(de-morgan `(not ,a))
                             ,(de-morgan `(not ,b))))
    (x (cons (car x) (mapcar #'de-morgan (rest x))))))

(de-morgan '(not (or 1 2))) ; => (and (not 1) (not 2))
(de-morgan '(not (and 1 2))) ; => (or (not 1) (not 2))
(de-morgan '(or a (and b (not (or c d))))) ; => (or a (and b (and (not c) (not d))))

你说“解除武装”;难道仅仅是在一个内部的“或”或“和”上分配“不是”吗?根据他的输出,这就是它看起来的样子。例如,“and”和“or”很容易就可以是“foo”和“bar”。逻辑似乎没有起到任何作用。处理人工智能让我想到谓词的使用,我的意思是你的程序应该首先学习一些知识(即如何根据DeMorgan定律解释不同的运算符),然后它可以使用其知识基础来评估你的整个表达式(即动态链接谓词)-参见谓词示例below@floppy12我同意。我更感兴趣的是学习解决这个问题的AI解决方案,而不是编辑字符串(像我的Java同事)和编辑列表(像我一样)。你是否建议我先教我的程序什么和或什么意思?“学习一些知识”我对实现感到困惑,但我确实理解您提出的要点?@RainerJoswig Oops,现在添加了not case。OP没有说是否应该删除双重否定。没有关于双重否定的说明,所以我认为它是开放式的。在我的emacs版本中,first和rest不存在。first与car相同,rest与cdr相同。对吗?我使用的是GNU emacs 24。但是是的,car是第一位的,cdr是其余的。您不应该在case中引用参数。
(case'quote('and'match)(t no match))
返回match,因为
的缩写(quote and)
,case需要一个用于键表单列表的指示符。您提供了一个包含两个符号的列表:quote和。@JoshuaTaylor:谢谢,这表明我现在很少使用lisp。我认为使用模式匹配(通过optima)会更干净一些。我认为Emacs Lisp也有一些与
pcase
的模式匹配,但我还没有充分使用它来知道它是否能用于此。@jkiiski:是的,模式匹配库会有很大帮助。a没有它就不会写代码,除了用于小练习。我理解反引号和逗号组合的作用。我正在尝试u理解,不管怎样。让我问一下我的回答是否正确:“(不是(或者,a,b))”(和(不是,(demorgan a)(不是,(demorgan b)基本上你是说,如果它匹配(不是(或者…),您正在通过demorgan函数运行a和b。您的最后一行让我感到困惑,您能解释一下吗?x到底绑定到了什么?@kaleoh在最后一行,
x
绑定到要匹配的表达式(与
exp
相同)。基本上是“否则”如果其他模式失败,将匹配任何内容的子句。如果它匹配单个原子,则该原子保持原样-良好。如果它匹配a'(not(和/或,a,b)),则替换为'(或/和(不是…),并在函数中同时运行a和b,非常棒。然后,如果它没有a'not,它将再次推动其余的函数,使其保持原样。非常棒!这正是我的意图,现在我知道了我希望在一周前知道的工具。中间的几行确实检查表达式是否匹配
(不匹配)(和))
,并将以
(或(不…(不…)
)的形式构建一个返回列表。由于
a
b
可能包含子列表,它们需要通过
de morgan
传递。我将调用移动到
de morgan
(不…)
。否则它将无法正确处理
(而不是(和a(和b c))