mirror of
https://github.com/RAIRLab/Spectra.git
synced 2025-06-06 01:05:41 +00:00
148 lines
5.3 KiB
Common Lisp
148 lines
5.3 KiB
Common Lisp
;;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: snark -*-
|
||
;;; File: variant.lisp
|
||
;;; The contents of this file are subject to the Mozilla Public License
|
||
;;; Version 1.1 (the "License"); you may not use this file except in
|
||
;;; compliance with the License. You may obtain a copy of the License at
|
||
;;; http://www.mozilla.org/MPL/
|
||
;;;
|
||
;;; Software distributed under the License is distributed on an "AS IS"
|
||
;;; basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||
;;; License for the specific language governing rights and limitations
|
||
;;; under the License.
|
||
;;;
|
||
;;; The Original Code is SNARK.
|
||
;;; The Initial Developer of the Original Code is SRI International.
|
||
;;; Portions created by the Initial Developer are Copyright (C) 1981-2011.
|
||
;;; All Rights Reserved.
|
||
;;;
|
||
;;; Contributor(s): Mark E. Stickel <stickel@ai.sri.com>.
|
||
|
||
(in-package :snark)
|
||
|
||
(defvar *extended-variant* nil)
|
||
|
||
(defun variant (cc x y &optional subst matches)
|
||
(macrolet
|
||
((variant1 (x y)
|
||
`(let ((v (assoc ,x matches)))
|
||
(cond
|
||
((null v)
|
||
(when (null (rassoc ,y matches))
|
||
(setf matches (acons ,x ,y matches))))
|
||
((eq (cdr v) ,y)
|
||
t)))))
|
||
(dereference2
|
||
x y subst
|
||
:if-constant*constant (cond
|
||
(*extended-variant*
|
||
(when (and (same-sort? (constant-sort x) (constant-sort y))
|
||
(variant1 x y))
|
||
(funcall cc matches)))
|
||
((eql x y)
|
||
(funcall cc matches)))
|
||
:if-compound*compound (let ((xhead (head x)) (yhead (head y)))
|
||
(cond
|
||
((and *extended-variant*
|
||
(not (function-logical-symbol-p xhead))
|
||
(not (function-logical-symbol-p yhead))
|
||
(not (eq *cons* xhead))
|
||
(not (eq *cons* yhead))
|
||
(not (equality-relation-symbol-p xhead))
|
||
(not (equality-relation-symbol-p yhead)))
|
||
(when (variant1 xhead yhead)
|
||
(variantl cc (argsa x) (argsa y) subst matches)))
|
||
((neq xhead yhead)
|
||
)
|
||
((eq *cons* xhead)
|
||
(prog->
|
||
(variant (car x) (car y) subst matches ->* matches)
|
||
(variant cc (cdr x) (cdr y) subst matches)))
|
||
(t
|
||
(let ((funs (function-variant-code xhead)))
|
||
(if funs
|
||
(dolist (fun funs)
|
||
(funcall fun cc x y subst matches))
|
||
(variantl cc (argsa x) (argsa y) subst matches))))))
|
||
:if-variable*variable (when (and (same-sort? (variable-sort x) (variable-sort y))
|
||
(variant1 x y))
|
||
(funcall cc matches)))))
|
||
|
||
(defun variantl (cc x y subst matches)
|
||
(cond
|
||
((null x)
|
||
(when (null y)
|
||
(funcall cc matches)))
|
||
((rest x)
|
||
(when (rest y)
|
||
(prog->
|
||
(variantl (rest x) (rest y) subst matches ->* matches)
|
||
(variant cc (first x) (first y) subst matches))))
|
||
((null (rest y))
|
||
(variant cc (first x) (first y) subst matches))))
|
||
|
||
(defun variant-p (x y &optional subst)
|
||
(prog->
|
||
(variant x y subst ->* matches)
|
||
(return-from variant-p (or matches t)))
|
||
nil)
|
||
|
||
(defun variant-bag (cc x y subst matches)
|
||
(variant-bag0 cc (args x) (args y) subst matches (head x)))
|
||
|
||
(defun variant-bag0 (cc terms1 terms2 subst matches fn)
|
||
(let ((counts1 (count-arguments fn terms1 subst))
|
||
(counts2 (count-arguments fn terms2 subst)))
|
||
(cond
|
||
((null counts1)
|
||
(when (null counts2)
|
||
(funcall cc subst)))
|
||
((null counts2)
|
||
)
|
||
((null (cdr counts1))
|
||
(when (null (cdr counts2))
|
||
(variant cc (tc-term (car counts1)) (tc-term (car counts2)) subst matches)))
|
||
((null (cdr counts2))
|
||
)
|
||
((and (length= (cddr counts1) (cddr counts2))
|
||
(submultisetp (let (w)
|
||
(dolist (tc counts1)
|
||
(push (tc-count tc) w))
|
||
w)
|
||
(let (w)
|
||
(dolist (tc counts2)
|
||
(push (tc-count tc) w))
|
||
w)))
|
||
(variant-bag* cc counts1 counts2 subst matches)))))
|
||
|
||
(defun variant-bag* (cc counts1 counts2 subst matches)
|
||
(let ((count1 (car counts1)))
|
||
(dolist (count2 counts2)
|
||
(when (eql (tc-count count1) (tc-count count2))
|
||
(cond
|
||
((null (cdr counts1))
|
||
(variant cc (tc-term count1) (tc-term count2) subst matches))
|
||
(t
|
||
(prog->
|
||
(variant (tc-term count1) (tc-term count2) subst matches ->* matches)
|
||
(variant-bag* cc (cdr counts1) (remove count2 counts2) subst matches))))))))
|
||
|
||
(defun variant-commute (cc x y subst matches)
|
||
;; It is assumed that commutative functions that are not assocative
|
||
;; have at least two arguments only the first two of which commute.
|
||
(let ((terms1 (args x))
|
||
(terms2 (args y)))
|
||
(variantl cc terms1 terms2 subst matches)
|
||
(variantl cc terms1 (list* (second terms2) (first terms2) (cddr terms2)) subst matches)))
|
||
|
||
(defun variant-vector (cc x y subst matches)
|
||
(let ((fn (head x))
|
||
(terms1 (args x))
|
||
(terms2 (args y)))
|
||
(and (or *extended-variant* (similar-argument-list-ac1-p fn terms1 terms2 subst))
|
||
(variantl cc
|
||
(argument-list-a1 fn terms1 subst)
|
||
(argument-list-a1 fn terms2 subst)
|
||
subst
|
||
matches))))
|
||
|
||
;;; variant.lisp EOF
|