src/binary-decision-diagrams.lisp @ b5708cf443c2
Rearrange vendor code
author |
Steve Losh <steve@stevelosh.com> |
date |
Sun, 21 Aug 2016 17:52:19 +0000 |
parents |
d1c9ad7b7774 |
children |
7eb23163afcf |
(in-package #:sand.binary-decision-diagrams)
(defun required ()
(error "Argument required."))
(defstruct (bdd (:constructor %make-bdd (number low high)))
(number (required) :type fixnum)
(low (required) :type (or bit bdd))
(high (required) :type (or bit bdd)))
(defun make-bdd (contents)
(etypecase contents
(bit contents)
(cons
(destructuring-bind (number low high) contents
(%make-bdd number (make-bdd low) (make-bdd high))))))
(defmacro bdd-case (bdd
((sink) &body sink-body)
((number low high) &body node-body))
(once-only (bdd)
`(etypecase ,bdd
(bit (let ((,sink ,bdd))
(declare (ignorable ,sink))
,@sink-body))
(bdd (with-accessors ((,number bdd-number)
(,low bdd-low)
(,high bdd-high))
,bdd
,@node-body)))))
(defun evaluate-bdd (bdd &rest arguments)
(recursively ((n 1)
(bdd bdd)
(argument (first arguments))
(remaining (rest arguments)))
(bdd-case bdd
((sink) sink)
((number low high)
(if (> number n)
(recur (1+ n)
bdd
argument
remaining)
(recur (1+ n)
(if (zerop argument)
low
high)
(first remaining)
(rest remaining)))))))
(defun bdd-map-nodes (function bdd)
(bdd-case bdd
((sink)
(list (funcall function sink)))
((n low high)
(append (list (funcall function bdd))
(bdd-map-nodes function low)
(bdd-map-nodes function high)))))
(defun bdd-map-edges (function bdd)
(bdd-case bdd
((sink) nil)
((n low high)
(list* (funcall function bdd low t)
(funcall function bdd high nil)
(append (bdd-map-edges function low)
(bdd-map-edges function high))))))
(defun node-label (node)
(bdd-case node
((sink) (if (zerop sink) 'false 'true))
((number low high) number)))
(defun node-shape (node)
(bdd-case node
((sink) :box)
((n l h) :circle)))
(defun draw-bdd (bdd &optional (path "bdd.dot"))
(let ((nodes (make-hash-table)))
(graphviz-digraph
(bdd-map-nodes (lambda (node)
(list (gethash-or-init node nodes (gensym))
:label (node-label node)
:shape (node-shape node)))
bdd)
(bdd-map-edges (lambda (a b lowp)
(list (gethash a nodes)
(gethash b nodes)
:style (if lowp :dashed :solid)))
bdd)
:path path)))
(defparameter *maj*
(make-bdd '(1
(2 0 (3 0 1))
(2 (3 0 1) 1))))
(draw-bdd *maj*)