psq.scm 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545
  1. #!r6rs
  2. ;;; psqs.sls --- Priority Search Queues
  3. ;; Copyright (C) 2012 Ian Price <ianprice90@googlemail.com>
  4. ;; Author: Ian Price <ianprice90@googlemail.com>
  5. ;; This program is free software, you can redistribute it and/or
  6. ;; modify it under the terms of the new-style BSD license.
  7. ;; You should have received a copy of the BSD license along with this
  8. ;; program. If not, see <http://www.debian.org/misc/bsd.license>.
  9. ;;;; Documentation
  10. ;;
  11. ;; Priority search queues are a combination of two common abstract
  12. ;; data types: finite maps, and priority queues. As such, it provides
  13. ;; for access, insertion, removal and update on arbitrary keys, as
  14. ;; well as for easy removal of the element with the lowest priority.
  15. ;;
  16. ;; Note: where a procedure takes a key or priority these are expected
  17. ;; to be compatible with the relevant ordering procedures on the psq.
  18. ;;
  19. ;;;; Basic operations
  20. ;;
  21. ;; make-psq : < < -> psq
  22. ;; takes a two ordering procedures, one for keys, and another for
  23. ;; priorities, and returns an empty priority search queue
  24. ;;
  25. ;; psq? : obj -> boolean
  26. ;; returns #t if the object is a priority search queue, #f otherwise.
  27. ;;
  28. ;; psq-empty? : psq -> boolean
  29. ;; returns #t if the priority search queue contains no elements, #f
  30. ;; otherwise.
  31. ;;
  32. ;; psq-size : psq -> non-negative integer
  33. ;; returns the number of associations in the priority search queue
  34. ;;
  35. ;;;; Finite map operations
  36. ;;
  37. ;; psq-ref : psq key -> priority
  38. ;; returns the priority of a key if it is in the priority search
  39. ;; queue. If the key is not in the priority queue an
  40. ;; assertion-violation is raised.
  41. ;;
  42. ;; psq-set : psq key priority -> psq
  43. ;; returns the priority search queue obtained from inserting a key
  44. ;; with a given priority. If the key is already in the priority search
  45. ;; queue, it updates the priority to the new value.
  46. ;;
  47. ;; psq-update : psq key (priority -> priority) priority -> psq
  48. ;; returns the priority search queue obtained by modifying the
  49. ;; priority of key, by the given function. If the key is not in the
  50. ;; priority search queue, it is inserted with the priority obtained by
  51. ;; calling the function on the default value.
  52. ;;
  53. ;; psq-delete : psq key -> psq
  54. ;; returns the priority search queue obtained by removing the
  55. ;; key-priority association from the priority search queue. If the key
  56. ;; is not in the queue, then the returned search queue will be the
  57. ;; same as the original.
  58. ;;
  59. ;; psq-contains? : psq key -> boolean
  60. ;; returns #t if there is an association for the given key in the
  61. ;; priority search queue, #f otherwise.
  62. ;;
  63. ;;;; Priority queue operations
  64. ;;
  65. ;; psq-min : psq -> key
  66. ;;
  67. ;; returns the key of the minimum association in the priority search
  68. ;; queue. If the queue is empty, an assertion violation is raised.
  69. ;;
  70. ;; psq-delete-min : psq -> psq
  71. ;; returns the priority search queue obtained by removing the minimum
  72. ;; association in the priority search queue. If the queue is empty, an
  73. ;; assertion violation is raised.
  74. ;;
  75. ;; psq-pop : psq -> key + psq
  76. ;; returns two values: the minimum key and the priority search queue
  77. ;; obtained by removing the minimum association from the original
  78. ;; queue. If the queue is empty, an assertion violation is raised.
  79. ;;
  80. ;;;; Ranged query functions
  81. ;;
  82. ;; psq-at-most : psq priority -> ListOf(key . priority)
  83. ;; returns an alist containing all the associations in the priority
  84. ;; search queue with priority less than or equal to a given value. The
  85. ;; alist returned is ordered by key according to the predicate for the
  86. ;; psq.
  87. ;;
  88. ;; psq-at-most-range : psq priority key key -> ListOf(key . priority)
  89. ;; Similar to psq-at-most, but it also takes an upper and lower bound,
  90. ;; for the keys it will return. These bounds are inclusive.
  91. ;;
  92. (library (fibers psq)
  93. (export make-psq
  94. psq?
  95. psq-empty?
  96. psq-size
  97. ;; map operations
  98. psq-ref
  99. psq-set
  100. psq-update
  101. psq-delete
  102. psq-contains?
  103. ;; priority queue operations
  104. psq-min
  105. psq-delete-min
  106. psq-pop
  107. ;; ranged query operations
  108. psq-at-most
  109. psq-at-most-range
  110. )
  111. (import (except (rnrs) min))
  112. ;;; record types
  113. (define-record-type void)
  114. (define-record-type winner
  115. (fields key priority loser-tree maximum-key))
  116. (define-record-type start)
  117. (define-record-type (loser %make-loser loser?)
  118. (fields size key priority left split-key right))
  119. (define (make-loser key priority left split-key right)
  120. (%make-loser (+ (size left) (size right) 1)
  121. key
  122. priority
  123. left
  124. split-key
  125. right))
  126. ;;; functions
  127. (define (maximum-key psq)
  128. (winner-maximum-key psq))
  129. (define max-key maximum-key)
  130. (define empty (make-void))
  131. (define (singleton key priority)
  132. (make-winner key priority (make-start) key))
  133. (define (play-match psq1 psq2 key<? prio<?)
  134. (cond ((void? psq1) psq2)
  135. ((void? psq2) psq1)
  136. ((not (prio<? (winner-priority psq2)
  137. (winner-priority psq1)))
  138. (let ((k1 (winner-key psq1))
  139. (p1 (winner-priority psq1))
  140. (t1 (winner-loser-tree psq1))
  141. (m1 (winner-maximum-key psq1))
  142. (k2 (winner-key psq2))
  143. (p2 (winner-priority psq2))
  144. (t2 (winner-loser-tree psq2))
  145. (m2 (winner-maximum-key psq2)))
  146. (make-winner k1
  147. p1
  148. (balance k2 p2 t1 m1 t2 key<? prio<?)
  149. m2)))
  150. (else
  151. (let ((k1 (winner-key psq1))
  152. (p1 (winner-priority psq1))
  153. (t1 (winner-loser-tree psq1))
  154. (m1 (winner-maximum-key psq1))
  155. (k2 (winner-key psq2))
  156. (p2 (winner-priority psq2))
  157. (t2 (winner-loser-tree psq2))
  158. (m2 (winner-maximum-key psq2)))
  159. (make-winner k2
  160. p2
  161. (balance k1 p1 t1 m1 t2 key<? prio<?)
  162. m2)))))
  163. (define (second-best ltree key key<? prio<?)
  164. (if (start? ltree)
  165. (make-void)
  166. (let ((k (loser-key ltree))
  167. (p (loser-priority ltree))
  168. (l (loser-left ltree))
  169. (m (loser-split-key ltree))
  170. (r (loser-right ltree)))
  171. (if (not (key<? m k))
  172. (play-match (make-winner k p l m)
  173. (second-best r key key<? prio<?)
  174. key<?
  175. prio<?)
  176. (play-match (second-best l m key<? prio<?)
  177. (make-winner k p r key)
  178. key<?
  179. prio<?)))))
  180. (define (delete-min psq key<? prio<?)
  181. ;; maybe void psqs should return void?
  182. (second-best (winner-loser-tree psq) (winner-maximum-key psq) key<? prio<?))
  183. (define (psq-case psq empty-k singleton-k match-k key<?)
  184. (if (void? psq)
  185. (empty-k)
  186. (let ((k1 (winner-key psq))
  187. (p1 (winner-priority psq))
  188. (t (winner-loser-tree psq))
  189. (m (winner-maximum-key psq)))
  190. (if (start? t)
  191. (singleton-k k1 p1)
  192. (let ((k2 (loser-key t))
  193. (p2 (loser-priority t))
  194. (l (loser-left t))
  195. (s (loser-split-key t))
  196. (r (loser-right t)))
  197. (if (not (key<? s k2))
  198. (match-k (make-winner k2 p2 l s)
  199. (make-winner k1 p1 r m))
  200. (match-k (make-winner k1 p1 l s)
  201. (make-winner k2 p2 r m))))))))
  202. (define (lookup psq key default key<?)
  203. (psq-case psq
  204. (lambda () default)
  205. (lambda (k p)
  206. (if (or (key<? k key) (key<? key k))
  207. default
  208. p))
  209. (lambda (w1 w2)
  210. (if (not (key<? (max-key w1) key))
  211. (lookup w1 key default key<?)
  212. (lookup w2 key default key<?)))
  213. key<?))
  214. (define (update psq key f default key<? prio<?)
  215. (psq-case psq
  216. (lambda () (singleton key (f default)))
  217. (lambda (k p)
  218. (cond ((key<? key k)
  219. (play-match (singleton key (f default))
  220. (singleton k p)
  221. key<?
  222. prio<?))
  223. ((key<? k key)
  224. (play-match (singleton k p)
  225. (singleton key (f default))
  226. key<?
  227. prio<?))
  228. (else
  229. (singleton key (f p)))))
  230. (lambda (w1 w2)
  231. (if (not (key<? (max-key w1) key))
  232. (play-match (update w1 key f default key<? prio<?)
  233. w2
  234. key<?
  235. prio<?)
  236. (play-match w1
  237. (update w2 key f default key<? prio<?)
  238. key<?
  239. prio<?)))
  240. key<?))
  241. (define (insert psq key val key<? prio<?)
  242. (psq-case psq
  243. (lambda () (singleton key val))
  244. (lambda (k p)
  245. (cond ((key<? key k)
  246. (play-match (singleton key val)
  247. (singleton k p)
  248. key<?
  249. prio<?))
  250. ((key<? k key)
  251. (play-match (singleton k p)
  252. (singleton key val)
  253. key<?
  254. prio<?))
  255. (else
  256. (singleton key val))))
  257. (lambda (w1 w2)
  258. (if (not (key<? (max-key w1) key))
  259. (play-match (insert w1 key val key<? prio<?) w2 key<? prio<?)
  260. (play-match w1 (insert w2 key val key<? prio<?) key<? prio<?)))
  261. key<?))
  262. (define (delete psq key key<? prio<?)
  263. (psq-case psq
  264. (lambda () empty)
  265. (lambda (k p)
  266. (if (or (key<? k key)
  267. (key<? key k))
  268. (singleton k p)
  269. empty))
  270. (lambda (w1 w2)
  271. (if (not (key<? (max-key w1) key))
  272. (play-match (delete w1 key key<? prio<?) w2 key<? prio<?)
  273. (play-match w1 (delete w2 key key<? prio<?) key<? prio<?)))
  274. key<?))
  275. (define (min tree)
  276. (when (void? tree)
  277. (assertion-violation 'psq-min
  278. "Can't take the minimum of an empty priority search queue"))
  279. (winner-key tree))
  280. (define (pop tree key<? prio<?)
  281. (when (void? tree)
  282. (assertion-violation 'psq-pop
  283. "Can't pop from an empty priority search queue"))
  284. (values (winner-key tree)
  285. (delete-min tree key<? prio<?)))
  286. ;; at-most and at-most-range are perfect examples of when to use
  287. ;; dlists, but we do not do that here
  288. (define (at-most psq p key<? prio<?)
  289. (define (at-most psq accum)
  290. (if (and (winner? psq)
  291. (prio<? p (winner-priority psq)))
  292. accum
  293. (psq-case psq
  294. (lambda () accum)
  295. (lambda (k p) (cons (cons k p) accum))
  296. (lambda (m1 m2)
  297. (at-most m1 (at-most m2 accum)))
  298. key<?)))
  299. (at-most psq '()))
  300. (define (at-most-range psq p lower upper key<? prio<?)
  301. (define (within-range? key)
  302. ;; lower <= k <= upper
  303. (not (or (key<? key lower) (key<? upper key))))
  304. (define (at-most psq accum)
  305. (if (and (winner? psq)
  306. (prio<? p (winner-priority psq)))
  307. accum
  308. (psq-case psq
  309. (lambda () accum)
  310. (lambda (k p)
  311. (if (within-range? k)
  312. (cons (cons k p) accum)
  313. accum))
  314. (lambda (m1 m2)
  315. (let ((accum* (if (key<? upper (max-key m1))
  316. accum
  317. (at-most m2 accum))))
  318. (if (key<? (max-key m1) lower)
  319. accum*
  320. (at-most m1 accum*))))
  321. key<?)))
  322. (at-most psq '()))
  323. ;;; Maintaining balance
  324. (define weight 4) ; balancing constant
  325. (define (size ltree)
  326. (if (start? ltree)
  327. 0
  328. (loser-size ltree)))
  329. (define (balance key priority left split-key right key<? prio<?)
  330. (let ((l-size (size left))
  331. (r-size (size right)))
  332. (cond ((< (+ l-size r-size) 2)
  333. (make-loser key priority left split-key right))
  334. ((> r-size (* weight l-size))
  335. (balance-left key priority left split-key right key<? prio<?))
  336. ((> l-size (* weight r-size))
  337. (balance-right key priority left split-key right key<? prio<?))
  338. (else
  339. (make-loser key priority left split-key right)))))
  340. (define (balance-left key priority left split-key right key<? prio<?)
  341. (if (< (size (loser-left right))
  342. (size (loser-right right)))
  343. (single-left key priority left split-key right key<? prio<?)
  344. (double-left key priority left split-key right key<? prio<?)))
  345. (define (balance-right key priority left split-key right key<? prio<?)
  346. (if (< (size (loser-right left))
  347. (size (loser-left left)))
  348. (single-right key priority left split-key right key<? prio<?)
  349. (double-right key priority left split-key right key<? prio<?)))
  350. (define (single-left key priority left split-key right key<? prio<?)
  351. (let ((right-key (loser-key right))
  352. (right-priority (loser-priority right))
  353. (right-left (loser-left right))
  354. (right-split-key (loser-split-key right))
  355. (right-right (loser-right right)))
  356. ;; test
  357. (if (and (not (key<? right-split-key right-key))
  358. (not (prio<? right-priority priority)))
  359. (make-loser key
  360. priority
  361. (make-loser right-key right-priority left split-key right-left)
  362. right-split-key
  363. right-right
  364. )
  365. (make-loser right-key
  366. right-priority
  367. (make-loser key priority left split-key right-left)
  368. right-split-key
  369. right-right))))
  370. (define (double-left key priority left split-key right key<? prio<?)
  371. (let ((right-key (loser-key right))
  372. (right-priority (loser-priority right))
  373. (right-left (loser-left right))
  374. (right-split-key (loser-split-key right))
  375. (right-right (loser-right right)))
  376. (single-left key
  377. priority
  378. left
  379. split-key
  380. (single-right right-key
  381. right-priority
  382. right-left
  383. right-split-key
  384. right-right
  385. key<?
  386. prio<?)
  387. key<?
  388. prio<?)))
  389. (define (single-right key priority left split-key right key<? prio<?)
  390. (let ((left-key (loser-key left))
  391. (left-priority (loser-priority left))
  392. (left-left (loser-left left))
  393. (left-split-key (loser-split-key left))
  394. (left-right (loser-right left)))
  395. (if (and (key<? left-split-key left-key)
  396. (not (prio<? left-priority priority)))
  397. (make-loser key
  398. priority
  399. left-left
  400. left-split-key
  401. (make-loser left-key left-priority left-right split-key right))
  402. (make-loser left-key
  403. left-priority
  404. left-left
  405. left-split-key
  406. (make-loser key priority left-right split-key right)))))
  407. (define (double-right key priority left split-key right key<? prio<?)
  408. (let ((left-key (loser-key left))
  409. (left-priority (loser-priority left))
  410. (left-left (loser-left left))
  411. (left-split-key (loser-split-key left))
  412. (left-right (loser-right left)))
  413. (single-right key
  414. priority
  415. (single-left left-key
  416. left-priority
  417. left-left
  418. left-split-key
  419. left-right
  420. key<?
  421. prio<?)
  422. split-key
  423. right
  424. key<?
  425. prio<?)))
  426. ;;; Exported Type
  427. (define-record-type (psq %make-psq psq?)
  428. (fields key<? priority<? tree))
  429. (define (%update-psq psq new-tree)
  430. (%make-psq (psq-key<? psq)
  431. (psq-priority<? psq)
  432. new-tree))
  433. ;;; Exported Procedures
  434. (define (make-psq key<? priority<?)
  435. (%make-psq key<? priority<? (make-void)))
  436. (define (psq-empty? psq)
  437. (assert (psq? psq))
  438. (void? (psq-tree psq)))
  439. (define (psq-ref psq key)
  440. (define cookie (cons #f #f))
  441. (assert (psq? psq))
  442. (let ((val (lookup (psq-tree psq) key cookie (psq-key<? psq))))
  443. (if (eq? val cookie)
  444. (assertion-violation 'psq-ref "not in tree")
  445. val)))
  446. (define (psq-set psq key priority)
  447. (assert (psq? psq))
  448. (%update-psq psq
  449. (insert (psq-tree psq) key priority (psq-key<? psq) (psq-priority<? psq))))
  450. (define (psq-update psq key f default)
  451. (assert (psq? psq))
  452. (%update-psq psq (update (psq-tree psq) key f default (psq-key<? psq) (psq-priority<? psq))))
  453. (define (psq-delete psq key)
  454. (assert (psq? psq))
  455. (%update-psq psq (delete (psq-tree psq) key (psq-key<? psq) (psq-priority<? psq))))
  456. (define (psq-contains? psq key)
  457. (define cookie (cons #f #f))
  458. (assert (psq? psq))
  459. (let ((val (lookup (psq-tree psq) key cookie (psq-key<? psq))))
  460. (not (eq? val cookie))))
  461. (define (psq-min psq)
  462. (assert (psq? psq))
  463. (min (psq-tree psq)))
  464. (define (psq-delete-min psq)
  465. (assert (and (psq? psq)
  466. (not (psq-empty? psq))))
  467. (%update-psq psq (delete-min (psq-tree psq) (psq-key<? psq) (psq-priority<? psq))))
  468. (define (psq-pop psq)
  469. (assert (psq? psq))
  470. (let-values (((min rest) (pop (psq-tree psq) (psq-key<? psq) (psq-priority<? psq))))
  471. (values min (%update-psq psq rest))))
  472. (define (psq-at-most psq max-priority)
  473. (assert (psq? psq))
  474. (let ((tree (psq-tree psq))
  475. (key<? (psq-key<? psq))
  476. (prio<? (psq-priority<? psq)))
  477. (at-most tree max-priority key<? prio<?)))
  478. (define (psq-at-most-range psq max-priority min-key max-key)
  479. (assert (psq? psq))
  480. (let ((tree (psq-tree psq))
  481. (key<? (psq-key<? psq))
  482. (prio<? (psq-priority<? psq)))
  483. (at-most-range tree max-priority min-key max-key key<? prio<?)))
  484. (define (psq-size psq)
  485. (assert (psq? psq))
  486. (let ((tree (psq-tree psq)))
  487. (if (winner? tree)
  488. (+ 1 (size (winner-loser-tree tree)))
  489. 0)))
  490. )