sparse-interpolate.scm 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;;; Sparse Multivariate Polynomial Interpolation
  21. ;;; a probabilistic method based on Richard Zippel's
  22. ;;; "Interpolating Polynomials From Their Values"
  23. ;;; TR89-963, Department of CS, Cornell University, January 1989
  24. ;;; coded and debugged by Gerald Jay Sussman and Dan Zuras
  25. ;;; June 1998
  26. ;;; This code differs from Zippel's in that it does not use modular
  27. ;;; arithmetic. This makes the idea stand out in stark contrast
  28. ;;; without the confusing complications introduced by those
  29. ;;; optimizations.
  30. (declare (usual-integrations))
  31. ;;; Given a polynomial function f of arity n and maximum degree d, to
  32. ;;; find a representation for the terms of the polynomial.
  33. (define (sparse-interpolate f n d)
  34. (let* ((rargs0 (generate-list (fix:- n 1) interpolate-random))
  35. (f1 (lambda (x) (apply f x rargs0)))
  36. (p1 (univariate-interpolate f1 d)))
  37. (let stagelp ;p has k vars interpolated
  38. ((k 1) (p p1) (rargs rargs0))
  39. (if (fix:= k n)
  40. p
  41. (let* ((fk
  42. (lambda (xk+1)
  43. (lambda x1-xk
  44. (apply f (append x1-xk (list xk+1) (cdr rargs))))))
  45. (xk+1s
  46. (generate-list (fix:+ d 1) interpolate-random))
  47. (ps
  48. (map (lambda (xk+1)
  49. (interpolate-skeleton (fk xk+1) p))
  50. xk+1s))
  51. (css
  52. (list-transpose
  53. (map (lambda (p)
  54. (map sparse-coefficient p))
  55. ps))))
  56. (let ((cps
  57. (let clp ((css css))
  58. (if (null? css)
  59. '()
  60. (univariate-interpolate-values xk+1s (car css)
  61. (lambda (cp) (cons cp (clp (cdr css))))
  62. (lambda () (stagelp k p rargs)))))))
  63. (stagelp (fix:+ k 1) (expand-poly p cps) (cdr rargs))))))))
  64. #|
  65. (sparse-interpolate
  66. (lambda (x y z) (+ (* 3 (square x) (cube y)) (* x y z) (* 4 z) 1))
  67. 3
  68. 4)
  69. ;Value: (((2 3 0) . 3) ((1 1 1) . 1) ((0 0 1) . 4) ((0 0 0) . 1))
  70. |#
  71. (define *interpolate-skeleton-using-vandermonde* #t)
  72. (define (interpolate-skeleton f skeleton-polynomial)
  73. (let ((skeleton (map sparse-exponents skeleton-polynomial))
  74. (arity (length (sparse-exponents (car skeleton-polynomial)))))
  75. (if *interpolate-skeleton-using-vandermonde*
  76. (let try-again ((args (generate-list arity interpolate-random)))
  77. (let* ((ones (make-list arity 1))
  78. (ks
  79. (map (lambda (exponent-list)
  80. (apply * (map expt args exponent-list)))
  81. skeleton))
  82. (ws
  83. (let lp ((i (length ks)) (argl ones) (fs '()))
  84. (if (fix:= i 0)
  85. (reverse! fs)
  86. (lp (fix:- i 1)
  87. (map * argl args)
  88. (cons (apply f argl) fs))))))
  89. (solve-vandermonde-t-system ks ws
  90. (lambda (coefficients)
  91. (filter (lambda (term)
  92. (not (zero? (sparse-coefficient term))))
  93. (map (lambda (exponent-list coefficient)
  94. (sparse-term exponent-list coefficient))
  95. skeleton
  96. coefficients)))
  97. (lambda ()
  98. (try-again (generate-list arity interpolate-random))))))
  99. (let ((new-args
  100. (lambda ()
  101. (generate-list (length skeleton-polynomial)
  102. (lambda (i)
  103. (generate-list arity interpolate-random))))))
  104. (let try-again ((trial-arglists (new-args)))
  105. (let ((matrix
  106. (matrix-by-row-list
  107. (map (lambda (argument-list)
  108. (map (lambda (exponent-list)
  109. (apply * (map expt argument-list exponent-list)))
  110. skeleton))
  111. trial-arglists)))
  112. (values
  113. (map (lambda (argl) (apply f argl))
  114. trial-arglists)))
  115. (lu-solve matrix
  116. (list->vector values)
  117. (lambda (coefficients)
  118. (filter (lambda (term)
  119. (not (zero? (sparse-coefficient term))))
  120. (map (lambda (exponent-list coefficient)
  121. (sparse-term exponent-list coefficient))
  122. skeleton
  123. (vector->list coefficients))))
  124. (lambda (ignore) (try-again (new-args))))))))))
  125. #|
  126. (interpolate-skeleton
  127. (lambda (x) (+ (* 3 (expt x 5)) (expt x 2) x 4))
  128. '(((5) . 1) ((2) . 1) ((1) . 1) ((0) . 1)))
  129. ;Value: (((5) . 3) ((2) . 1) ((1) . 1) ((0) . 4))
  130. |#
  131. (define (expand-poly p cps)
  132. (sort
  133. (apply append
  134. (map (lambda (skel-term cp)
  135. (let ((old-exponents (sparse-exponents skel-term)))
  136. (map (lambda (coeff-term)
  137. (sparse-term
  138. (append old-exponents (sparse-exponents coeff-term))
  139. (sparse-coefficient coeff-term)))
  140. cp)))
  141. p cps))
  142. sparse-term->))
  143. #|
  144. (pp (expand-poly '(((5) . 3) ((2) . 1) ((1) . 1) ((0) . 4))
  145. '( (((1) . 1) ((0) . 3))
  146. (((1) . 1))
  147. (((3) . 2) ((0) . 4))
  148. (((1) . 2) ((0) . 5)) )))
  149. (((5 1) . 1) ((5 0) . 3) ((1 3) . 2) ((2 1) . 1) ((1 0) . 4) ((0 1) . 2) ((0 0) . 5))
  150. |#
  151. ;;; f is a univariate polynomial function.
  152. ;;; d+1 is the number of unknown coefficients.
  153. ;;; (usually d is the degree of the polynomial)
  154. (define (univariate-interpolate f d)
  155. (let* ((xs (generate-list (+ d 1) interpolate-random))
  156. (fs (map f xs)))
  157. (univariate-interpolate-values
  158. xs
  159. fs
  160. (lambda (poly) poly)
  161. (lambda () (univariate-interpolate f d)))))
  162. (define (univariate-interpolate-values xs fs succeed fail)
  163. (solve-vandermonde-system xs fs
  164. (lambda (coefficients)
  165. (succeed (reverse
  166. (filter (lambda (term)
  167. (not (zero? (sparse-coefficient term))))
  168. (map (lambda (exponent coefficient)
  169. (sparse-term (list exponent)
  170. coefficient))
  171. (iota (length xs))
  172. coefficients)))))
  173. fail))
  174. (define *interpolate-size* 10000)
  175. (define (interpolate-random i)
  176. (+ (random *interpolate-size*) 1))
  177. #|
  178. (univariate-interpolate
  179. (lambda (x) (+ (* 3 (expt x 5)) (expt x 2) x 4))
  180. 6)
  181. ;Value: (((5) . 3) ((2) . 1) ((1) . 1) ((0) . 4))
  182. |#
  183. #|
  184. (define (old-univariate-interpolate-values xs fs succeed fail)
  185. (let ((n (length xs)))
  186. (assert (fix:= n (length fs)))
  187. (let* ((exponents (iota n))
  188. (matrix
  189. (matrix-by-row-list
  190. (map (lambda (x)
  191. (map (lambda (e) (expt x e))
  192. exponents))
  193. xs))))
  194. (lu-solve matrix
  195. (list->vector fs)
  196. (lambda (coefficients)
  197. (succeed (reverse
  198. (filter (lambda (term)
  199. (not (zero? (sparse-coefficient term))))
  200. (map (lambda (exponent coefficient)
  201. (sparse-term (list exponent)
  202. coefficient))
  203. exponents
  204. (vector->list coefficients))))))
  205. (lambda (ignore) (fail))))))
  206. ;;; Check that the new algorithm is equivalent to the old one, and faster
  207. (define (check m)
  208. (let ((xs (generate-list m interpolate-random))
  209. (fs (generate-list m interpolate-random)))
  210. (let ((t0 (runtime)))
  211. (univariate-interpolate-values xs fs
  212. (lambda (new-result)
  213. (let ((t1 (runtime)))
  214. (old-univariate-interpolate-values xs fs
  215. (lambda (old-result)
  216. (let ((t2 (runtime)) (e (equal? old-result new-result)))
  217. ;;(pp (list '+ (- t1 t0) (- t2 t1)))
  218. (assert e)))
  219. (lambda ()
  220. (pp (list 'old-failed-new-won xs fs new-result))))))
  221. (lambda ()
  222. (let ((t1 (runtime)))
  223. (old-univariate-interpolate-values xs fs
  224. (lambda (old-result)
  225. (pp (list 'new-failed-old-won xs fs old-result)))
  226. (lambda ()
  227. (let ((t2 (runtime)))
  228. ;;(pp (list '* (- t1 t0) (- t2 t1)))
  229. )
  230. 'both-failed))))))))
  231. (let lp ((i 100000))
  232. (if (fix:= i 0)
  233. 'done
  234. (begin (check 30)
  235. (lp (fix:- i 1)))))
  236. ;;; Increase failure rate to about 40% for size 30 problems.
  237. (set! *interpolate-size* 1000)
  238. |#