Arrays 确定位数组是否在位数组集合中
给定二维NxN位数组,我正在尝试评估确定位数组是否已经在以前看到的大量位数组集合中的最佳方法 一种简单的方法是将位数组放入哈希表中。但是比较数组需要一个#'equalp:test函数,这可能不是很有效。(但SBCL可能会自动针对不同的密钥类型进行优化?) 另一个计划是将所有位数组转换为整数,并将整数放入哈希表中。那么测试可以是#eql: 不过,不确定这是否会比让SBCL处理事情更有效,因为它仍然单独处理每个元素。也许定制的哈希表会带来效率优势 第三个选项可能涉及将基本表示形式从位数组更改为简单位向量(也称为整数),因为原始位数组的维度是已知的。为了允许数组等效元素引用,这需要一个函数将隐式数组行、列坐标转换为显式简单位向量索引。根据需要计算索引可能比在每次哈希表查找时将整个位数组转换为整数更有效,如上所述Arrays 确定位数组是否在位数组集合中,arrays,common-lisp,bitarray,bitvector,Arrays,Common Lisp,Bitarray,Bitvector,给定二维NxN位数组,我正在尝试评估确定位数组是否已经在以前看到的大量位数组集合中的最佳方法 一种简单的方法是将位数组放入哈希表中。但是比较数组需要一个#'equalp:test函数,这可能不是很有效。(但SBCL可能会自动针对不同的密钥类型进行优化?) 另一个计划是将所有位数组转换为整数,并将整数放入哈希表中。那么测试可以是#eql: 不过,不确定这是否会比让SBCL处理事情更有效,因为它仍然单独处理每个元素。也许定制的哈希表会带来效率优势 第三个选项可能涉及将基本表示形式从位数组更改为简单位
欣赏一些有经验的见解。我认为知道这一点的唯一方法是尝试一些事情,看看什么是最快的 您可以尝试的一个可怕的技巧是将位向量表示为
(行长度.位整数)
的cons。您需要行长度,以便可以计算位整数中的偏移量。然后你可以这样做(这些可能是错误的,因为我总是被dpb
和ldb
弄糊涂了):
(定义类型索引()
`(整数0,最大正fixnum))
(定义make bv(列)
(声明(类型索引列))
(第0栏)
(定义bv ref(bv行-列)
(声明(类型(cons索引整数)bv)
(类型索引行列))
(let((列(car bv)))
(断言(<列列)(列)“列超出范围”)
(ldb(字节1(+(*行-列)列))(cdr bv)))
(定义(setf bv ref)(位bv行-列)
(声明(类型位)
(类型(cons索引整数)bv)
(类型索引行列))
(let((列(car bv)))
(断言(<列列)(列)“列超出范围”)
(setf(cdr bv)(dpb位(字节1(+(*行-列)列))(cdr bv)))
位)
在现实生活中,你当然想把这些东西内联起来
这样的表示可能适合于散列(您可以在equal
上散列,或者甚至在cons中为两个元素嵌套eql
哈希表),但值得注意的问题是它不关心对象有多少行:它们基本上都有无限多的行
如果“数组”非常大,并且你在其中改变了很多位,那就太糟糕了,因为每次你改变一点,它都会限制一个新的bignum
但我认为知道的唯一方法是测量。感谢您概述了我可以尝试的有趣的第三个选项。我最积极的fixnum是4611686018427387903,所以看起来我可以有效地处理多达7x7位的数组=49<62位。如果行长度是全局的,则可能不需要cons。还感谢您为ldb和dpb提供的指导,这需要一些研究。
(defun bit-arr-to-int (bit-array)
(reduce (lambda (bit1 bit2)
(+ (* bit1 2) bit2))
(make-array (array-total-size bit-array)
:displaced-to bit-array)))
(deftype index ()
`(integer 0 ,most-positive-fixnum))
(defun make-bv (columns)
(declare (type index columns))
(cons columns 0))
(defun bv-ref (bv row column)
(declare (type (cons index integer) bv)
(type index row column))
(let ((columns (car bv)))
(assert (< column columns) (column) "column out of range")
(ldb (byte 1 (+ (* row columns) column)) (cdr bv))))
(defun (setf bv-ref) (bit bv row column)
(declare (type bit bit)
(type (cons index integer) bv)
(type index row column))
(let ((columns (car bv)))
(assert (< column columns) (column) "column out of range")
(setf (cdr bv) (dpb bit (byte 1 (+ (* row columns) column)) (cdr bv)))
bit))