sparse.scm 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  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 flat form support for interpolation and gcd.
  21. (declare (usual-integrations))
  22. ;;; These algorithms work on the termlists of the flat multivariate
  23. ;;; polynomial form that is defined in the file fpf. A flat sparse
  24. ;;; polynomial is a list of terms, each of which is the cons of an
  25. ;;; exponent list and a coefficient. This package uses this format,
  26. ;;; but attempts to stand on its own: it does not use the fpf:xxx
  27. ;;; definitions. This produces redundant code, but it is easier to
  28. ;;; work with the independent mechanism this way.
  29. (define (sparse-exponents term) (car term))
  30. (define (sparse-coefficient term) (cdr term))
  31. (define (sparse-term exponents coefficient)
  32. (cons exponents coefficient))
  33. (define (sparse-constant-term? term)
  34. (for-all? (sparse-exponents term) zero?))
  35. (define (sparse-univariate? p)
  36. (and (pair? p)
  37. (fix:= (length (sparse-exponents (car p)))
  38. 1)))
  39. (define (sparse-constant? p)
  40. (and (fix:= (length p) 1)
  41. (sparse-constant-term? (car p))))
  42. (define (sparse-one-term? t)
  43. (and (sparse-constant-term? t)
  44. (= (sparse-coefficient t) 1)))
  45. (define (sparse-one? p)
  46. (and (sparse-constant? p)
  47. (= (sparse-coefficient (car p)) 1)))
  48. (define (sparse-zero? p)
  49. (null? p))
  50. (define (sparse-zero-term? t)
  51. (and (sparse-constant-term? t)
  52. (= (sparse-coefficient t) 0)))
  53. (define (sparse-constant-term arity-n constant)
  54. (sparse-term (make-list arity-n 0) constant))
  55. (define (sparse-one arity-n)
  56. (list (sparse-constant-term arity-n 1)))
  57. (define (sparse-identity-term arity-n varnum)
  58. (sparse-term (generate-list arity-n
  59. (lambda (i)
  60. (if (fix:= i varnum) 1 0)))
  61. 1))
  62. (define (sparse-linear arity-n varnum root)
  63. (if (zero? root)
  64. (list (sparse-identity-term arity-n varnum))
  65. (list (sparse-identity-term arity-n varnum)
  66. (sparse-constant-term arity-n (- root)))))
  67. (define (sparse-term-> t1 t2)
  68. (sparse:>exponents? (sparse-exponents t1)
  69. (sparse-exponents t2)))
  70. ;;; Graded Lexicographical Order
  71. (define (sparse:>exponents? fs1 fs2)
  72. (let ((o1 (reduce fix:+ 0 fs1))
  73. (o2 (reduce fix:+ 0 fs2)))
  74. (cond ((fix:> o1 o2) #t)
  75. ((fix:< o1 o2) #f)
  76. (else
  77. (let lp ((l1 fs1) (l2 fs2))
  78. (cond ((null? l1) #f)
  79. ((null? l2) #t)
  80. ((fix:> (car l1) (car l2)) #t)
  81. ((fix:< (car l1) (car l2)) #f)
  82. (else (lp (cdr l1) (cdr l2)))))))))
  83. #|
  84. ;;; Lexicographical Order
  85. (define (sparse:>exponents? fs1 fs2)
  86. (let lp ((l1 fs1) (l2 fs2))
  87. (cond ((null? l1) #f)
  88. ((null? l2) #t)
  89. ((fix:> (car l1) (car l2)) #t)
  90. ((fix:< (car l1) (car l2)) #f)
  91. (else (lp (cdr l1) (cdr l2))))))
  92. |#
  93. (define (sparse-normalize poly term)
  94. (if (or (and (number? term) (= term 1))
  95. (sparse-one-term? term))
  96. poly
  97. (map (lambda (pterm)
  98. (sparse-term
  99. (map - (sparse-exponents pterm) (sparse-exponents term))
  100. (/ (sparse-coefficient pterm) (sparse-coefficient term))))
  101. poly)))
  102. (define (sparse-scale poly term)
  103. (if (or (and (number? term) (= term 1))
  104. (sparse-one-term? term))
  105. poly
  106. (map (lambda (pterm)
  107. (sparse-term
  108. (map + (sparse-exponents pterm) (sparse-exponents term))
  109. (* (sparse-coefficient pterm) (sparse-coefficient term))))
  110. poly)))
  111. (define (sparse-negate-term t)
  112. (sparse-term (sparse-exponents t) (- (sparse-coefficient t))))
  113. (define (sparse-add xlist ylist)
  114. (let tloop ((xlist xlist) (ylist ylist))
  115. (cond ((null? xlist) ylist)
  116. ((null? ylist) xlist)
  117. (else
  118. (let ((e1 (sparse-exponents (car xlist)))
  119. (e2 (sparse-exponents (car ylist))))
  120. (cond ((equal? e1 e2)
  121. (let ((ncoeff (+ (sparse-coefficient (car xlist))
  122. (sparse-coefficient (car ylist)))))
  123. (if (= ncoeff 0)
  124. (tloop (cdr xlist) (cdr ylist))
  125. (cons (sparse-term e1 ncoeff)
  126. (tloop (cdr xlist) (cdr ylist))))))
  127. ((sparse:>exponents? e1 e2)
  128. (cons (car xlist) (tloop (cdr xlist) ylist)))
  129. (else
  130. (cons (car ylist) (tloop xlist (cdr ylist))))))))))
  131. (define (sparse-multiply xlist ylist)
  132. (let lp ((xlist xlist))
  133. (if (null? xlist)
  134. '()
  135. (sparse-add (sparse-multiply-term (car xlist) ylist)
  136. (lp (cdr xlist))))))
  137. (define (sparse-multiply-term t x)
  138. (let ((exponents (sparse-exponents t))
  139. (coeff (sparse-coefficient t)))
  140. (map (lambda (term)
  141. (sparse-term (map + exponents (sparse-exponents term))
  142. (* coeff (sparse-coefficient term))))
  143. x)))
  144. (define (sparse-abs p)
  145. (if (null? p)
  146. '()
  147. (if (let ((c (sparse-coefficient (car p))))
  148. (and (real? c) (< c 0)))
  149. (map (lambda (term)
  150. (sparse-term (sparse-exponents term)
  151. (- (sparse-coefficient term))))
  152. p)
  153. p)))
  154. (define (sparse-divide numerator-terms denominator-terms cont)
  155. (let ((dexps (sparse-exponents (car denominator-terms)))
  156. (dcoef (sparse-coefficient (car denominator-terms))))
  157. (define (dloop nterms cont)
  158. (if (null? nterms)
  159. (cont '() '())
  160. (let ((nexps (sparse-exponents (car nterms)))
  161. (ncoef (sparse-coefficient (car nterms))))
  162. (cond ((&and (map >= nexps dexps)) ;monomial-divisible?
  163. (let ((qt (sparse-term (map - nexps dexps)
  164. (/ ncoef dcoef))))
  165. (dloop
  166. (sparse-add (cdr nterms)
  167. (sparse-multiply-term (sparse-negate-term qt)
  168. (cdr denominator-terms)))
  169. (lambda (q r)
  170. (cont (sparse-add (list qt) q) r)))))
  171. (else
  172. (dloop (cdr nterms)
  173. (lambda (q r)
  174. (cont q
  175. (sparse-add (list (car nterms))
  176. r)))))))))
  177. (dloop numerator-terms cont)))
  178. (define (sparse-divisible? n d)
  179. (null? (sparse-divide n d (lambda (q r) r))))
  180. #|
  181. ;;; This was a bad idea. It actually gives wrong answers:
  182. ;;; (x+1)/3 = 1/3 x + 1/3 but for x=6 7/3 is not integer divisible.
  183. (define *heuristic-sparse-divisible-enabled* #t)
  184. ;;; Effectiveness Statistics
  185. (define *heuristic-sparse-divisible-win* 0)
  186. (define *heuristic-sparse-divisible-lose* 0)
  187. (define *heuristic-sparse-divisible-bad-decision* 0)
  188. (define *heuristic-sparse-divisible-testing* #t)
  189. (define (sparse-divisible? n d)
  190. (if *heuristic-sparse-divisible-enabled*
  191. (let ((m (length (sparse-exponents (car n)))))
  192. (let ((na (sparse-evaluate n (generate-list m interpolate-random)))
  193. (da (sparse-evaluate d (generate-list m interpolate-random))))
  194. (if (and (integer? na) (integer? da) (zero? (remainder na da)))
  195. (let ((val (null? (sparse-divide n d (lambda (q r) r)))))
  196. (set! *heuristic-sparse-divisible-lose*
  197. (+ *heuristic-sparse-divisible-lose* 1))
  198. (if (not val)
  199. (set! *heuristic-sparse-divisible-bad-decision*
  200. (+ *heuristic-sparse-divisible-bad-decision* 1)))
  201. val)
  202. (begin
  203. (set! *heuristic-sparse-divisible-win*
  204. (+ *heuristic-sparse-divisible-win* 1))
  205. (if *heuristic-sparse-divisible-testing*
  206. (let ((val (null? (sparse-divide n d (lambda (q r) r)))))
  207. (if val
  208. (begin (bkpt "Wrong answer! sparse-divisible")
  209. val)
  210. val))
  211. #f)))))
  212. (null? (sparse-divide n d (lambda (q r) r)))))
  213. |#
  214. (define (fpf:->sparse p)
  215. (fpf:terms p))
  216. #|
  217. (define (divide-test q d r)
  218. (let ((pq (fpf:expression-> q (lambda (p v) p)))
  219. (pd (fpf:expression-> d (lambda (p v) p)))
  220. (pr (fpf:expression-> r (lambda (p v) p))))
  221. (let ((pn (fpf:+ (fpf:* pq pd) pr))
  222. (sq (fpf:->sparse pq))
  223. (sr (fpf:->sparse pr)))
  224. (let ((sn (fpf:->sparse pn))
  225. (sd (fpf:->sparse pd)))
  226. ;; n = q*d + r
  227. (sparse-divide sn sd
  228. (lambda (q r)
  229. (pp `((sn ,sn) = (q ,q) * (d ,sd) + (r ,r)))
  230. (if (and (equal? q sq) (equal? r sr))
  231. (pp #t)
  232. (pp `((sq ,sq) (sr ,sr))))))))))
  233. |#
  234. ;;; Evaluation of polynomials at argument lists.
  235. (define (sparse-evaluate p x)
  236. (if (null? p)
  237. 0
  238. (begin
  239. (assert (fix:= (length x)
  240. (length (sparse-exponents (car p)))))
  241. (apply +
  242. (map (lambda (term)
  243. (* (sparse-coefficient term)
  244. (apply *
  245. (map expt
  246. x
  247. (sparse-exponents term)))))
  248. p)))))
  249. ;;; If x is smaller than the arity of p then the last vars are filled
  250. ;;; in by components of x, making a polynomial of lesser arity.
  251. (define (sparse-evaluate> p x)
  252. (if (or (null? x) (null? p))
  253. p
  254. (let* ((n (length x))
  255. (arity (length (sparse-exponents (car p))))
  256. (narity (- arity n)))
  257. (sparse-combine-like-terms
  258. (map (lambda (term)
  259. (sparse-term (list-head (sparse-exponents term) narity)
  260. (* (sparse-coefficient term)
  261. (apply *
  262. (map expt
  263. x
  264. (list-tail (sparse-exponents term)
  265. narity))))))
  266. p)))))
  267. #|
  268. (print-expression
  269. (sparse-evaluate>
  270. '(((2 3 0) . 3) ((1 1 1) . 1) ((0 0 1) . 4) ((0 0 0) . 1))
  271. '(y z)))
  272. (((2) . (* 3 (expt y 3))) ((1) . (* y z)) ((0) . (* 4 z)) ((0) . 1))
  273. |#
  274. (define (sparse-evaluate< p x)
  275. (if (or (null? x) (null? p))
  276. p
  277. (let ((n (length x)))
  278. (sparse-combine-like-terms
  279. (map (lambda (term)
  280. (sparse-term (list-tail (sparse-exponents term) n)
  281. (* (sparse-coefficient term)
  282. (apply *
  283. (map expt
  284. x
  285. (list-head (sparse-exponents term)
  286. n))))))
  287. p)))))
  288. #|
  289. (print-expression
  290. (sparse-evaluate<
  291. '(((2 3 0) . 3) ((1 1 1) . 1) ((0 0 1) . 4) ((0 0 0) . 1))
  292. '(x y)))
  293. (((1) . (+ 4 (* x y))) ((0) . (+ 1 (* 3 (expt x 2) (expt y 3)))))
  294. |#
  295. (define (sparse-combine-like-terms terms)
  296. (sparse-merge-adjacent-terms (sort terms sparse-term->)))
  297. (define (sparse-merge-adjacent-terms terms)
  298. (cond ((null? terms)
  299. '())
  300. ((null? (cdr terms))
  301. (if (= (sparse-coefficient (car terms)) 0)
  302. '()
  303. terms))
  304. ((equal? (sparse-exponents (car terms))
  305. (sparse-exponents (cadr terms)))
  306. (let ((coeff (+ (sparse-coefficient (car terms))
  307. (sparse-coefficient (cadr terms)))))
  308. (if (= coeff 0)
  309. (sparse-merge-adjacent-terms (cddr terms))
  310. (sparse-merge-adjacent-terms
  311. (cons (sparse-term (sparse-exponents (car terms))
  312. coeff)
  313. (cddr terms))))))
  314. (else
  315. (cons (car terms)
  316. (sparse-merge-adjacent-terms (cdr terms))))))