这是一个长期存在的难题。
h2. 问题
经典示例是缩短含有恶意元素的 2D 矩阵
(def gen-matrix
(gen/let [width gen/nat]
(gen/vector (gen/vector gen/large-integer width))))
(quick-check 10000
(prop/for-all [matrix gen-matrix]
(->> matrix
(apply concat)
(not-any? #{42}))))
;; =>
{:result false,
:seed 1466646880334,
:failing-size 16,
:num-tests 17,
:fail [[[290 42 10 3 1 3 196]
[-1793 3484 -5795 -206 -1 -8 464]
[2 3 -1951 -761 -28829 5518 1]
[-32 4477 1 -4086 0 1640 -22185]
[-485 3156 -625 4082 -2 -845 513]
[-3 -1 26 323 232 5 -1]
[32 51 -1 240 -1814 0 -190]
[2417 -4239 326 -4096 -8 1898 75]
[-509 1 0 466 199 -1 10]
[-23 5838 -441 30741 -6724 -1169 -171]
[-4 3974 -1432 -4 698 -56 1210]
[-2148 -6526 -1 453 19 -5343 461]]],
:shrunk {:total-nodes-visited 31,
:depth 8,
:result false,
;; 若缩减到 [[[42]]] 将会更好
;;
;; 注意此处可能的最小值宽度(7
;; 与原始失败情况相同
;; 唯一的原因是运气好,生成了一个等
;; 于缩小宽度的新矩阵,偶然包含元素 42
:smallest [[[0 42 0]]]}}
h2. 灵感
-
https://twitter.com/jacobstanley/status/745790758972624896-
https://twitter.com/DRMacIver/status/737390842462212096- 在最后一个失败案例中重用值的一种最佳尝试方法
如果我们将复合发生器每个子生成器生成的事物记录下来,然后在缩减生成器运行时使用生成器相等性来尝试重放这些值...这会很混乱,但我认为混乱对用户来说是不可见的。