simplify.scm 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. ;;;; General Recursive Simplifier Maker
  21. ;;; Given a set of operations, this procedure makes a recursive
  22. ;;; simplifier that simplifies expressions involving these
  23. ;;; operations, treating other combinations as atomic.
  24. ;;; To break an expression up into manipulable and nonmanipulable
  25. ;;; parts with respect to a set of algebraic operators. This is done
  26. ;;; by the introduction of auxiliary variables.
  27. ;;; For example, the equation
  28. ;;; I = Is (exp((V2 - V3)/Vt) - 1) ; I, V2, V3
  29. ;;; can be broken into three equations
  30. ;;; I + Is = Is*X ; I, X
  31. ;;; V2/Vt - V3/Vt = Y ; V2, V3, Y
  32. ;;; X = (exp Y) ; X, Y
  33. ;;; where X and Y are new variables. The first two parts contain only
  34. ;;; addition, subtraction, multiplication, and division and the third
  35. ;;; is not expressible in terms of those operations.
  36. (declare (usual-integrations))
  37. ;;; Exponential expressions with non-integer exponents must become
  38. ;;; kernels, because they cannot become polynomial exponentials.
  39. (define *inhibit-expt-simplify* #t)
  40. (define (make-analyzer ->expression expression-> known-operators)
  41. ;; FBE: need to initialize the variables
  42. (let ;;((auxiliary-variable-table) (reverse-table) (uorder) (priority))
  43. ((auxiliary-variable-table unspecific) (reverse-table unspecific)
  44. (uorder unspecific) (priority unspecific))
  45. ;; Default simplifier
  46. (define (simplify expr)
  47. (new-analysis)
  48. (simplify-expression expr))
  49. ;; Simplify relative to existing tables
  50. (define (simplify-expression expr)
  51. (backsubstitute (analyze-expression expr)))
  52. ;; Analyze relative to existing tables
  53. ;;; FBE use parameterize instead of fluid-let
  54. ;; (define (analyze-expression expr)
  55. ;; (fluid-let ((incremental-simplifier #f))
  56. ;; (base-simplify (analyze expr))))
  57. (define (analyze-expression expr)
  58. (parameterize ((incremental-simplifier #f))
  59. (base-simplify (analyze expr))))
  60. ;; Set up new analysis
  61. (define (new-analysis)
  62. (set! auxiliary-variable-table
  63. ((weak-hash-table/constructor equal-hash-mod equal? #t)))
  64. (set! reverse-table (make-eq-hash-table))
  65. (set! uorder '())
  66. (set! priority '())
  67. 'done)
  68. ;; Define ordering of variables
  69. (define (set-priority! . exprs)
  70. (set! priority (map add-symbol! exprs))
  71. priority)
  72. ;; Get kernel table
  73. (define (get-auxiliary-variable-defs)
  74. (map (lambda (entry)
  75. (list (cdr entry) (car entry)))
  76. (hash-table->alist auxiliary-variable-table)))
  77. ;; Implementation -----------------------
  78. (define (analyze expr)
  79. (let ((vars (sort (variables-in expr) variable<?)))
  80. (set! uorder
  81. (append (map add-symbol! priority)
  82. vars)))
  83. (ianalyze expr))
  84. (define (ianalyze expr)
  85. (if (and (pair? expr) (not (eq? (car expr) 'quote)))
  86. (let ((sexpr (map ianalyze expr)))
  87. ;; At this point all subexpressions are canonical.
  88. (if (and (memq (operator sexpr) known-operators)
  89. (not (and *inhibit-expt-simplify*
  90. (expt? sexpr)
  91. (not (exact-integer? (cadr (operands sexpr)))))))
  92. sexpr
  93. (let ((as-seen (expression-seen sexpr)))
  94. (if as-seen
  95. as-seen
  96. (new-kernels sexpr)))))
  97. expr))
  98. (define (new-kernels expr)
  99. (let ((sexpr (map base-simplify expr)))
  100. (let ((v (hash-table/get symbolic-operator-table
  101. (operator sexpr)
  102. #f)))
  103. (if v
  104. (let ((w (apply v (operands sexpr))))
  105. (if (and (pair? w) (eq? (operator w) (operator sexpr)))
  106. (add-symbols! w)
  107. (ianalyze w)))
  108. (add-symbols! sexpr)))))
  109. (define (base-simplify expr)
  110. (if (and (pair? expr) (not (eq? (car expr) 'quote)))
  111. (expression-> expr ->expression vless?)
  112. expr))
  113. (define (backsubstitute expr)
  114. (define lp
  115. (lambda (expr)
  116. (cond ((pair? expr) (map lp expr))
  117. ((symbol? expr)
  118. (let ((v (hash-table/get reverse-table expr #f)))
  119. (if v (lp v) expr)))
  120. (else expr))))
  121. (lp expr))
  122. (define (add-symbols! expr)
  123. (let ((new (map add-symbol! expr)))
  124. (add-symbol! new)))
  125. (define (add-symbol! expr)
  126. (if (and (pair? expr) (not (eq? (car expr) 'quote)))
  127. (let ((as-seen (expression-seen expr)))
  128. (if as-seen
  129. as-seen
  130. (let ((newvar
  131. (generate-uninterned-symbol "kernel")))
  132. (hash-table/put! auxiliary-variable-table expr newvar)
  133. (hash-table/put! reverse-table newvar expr)
  134. newvar)))
  135. expr))
  136. (define (expression-seen expr)
  137. (hash-table/get auxiliary-variable-table expr #f))
  138. (define (vless? var1 var2)
  139. (let ((in (memq var1 uorder)))
  140. (cond (in
  141. (cond ((memq var2 in) true)
  142. ((memq var2 uorder) false)
  143. (else true)))
  144. ((memq var2 uorder) false)
  145. (else
  146. (variable<? var1 var2)))))
  147. (new-analysis)
  148. (vector simplify
  149. simplify-expression
  150. new-analysis
  151. set-priority!
  152. analyze-expression
  153. get-auxiliary-variable-defs)))
  154. (define (default-simplifier analyzer) (vector-ref analyzer 0))
  155. (define (expression-simplifier analyzer) (vector-ref analyzer 1))
  156. (define (initializer analyzer) (vector-ref analyzer 2))
  157. (define (priority-setter analyzer) (vector-ref analyzer 3))
  158. (define (expression-analyzer analyzer) (vector-ref analyzer 4))
  159. (define (auxiliary-variable-fetcher analyzer) (vector-ref analyzer 5))
  160. (define fpf:analyzer
  161. (make-analyzer fpf:->expression fpf:expression-> fpf:operators-known))
  162. ;;(define fpf:simplify (default-simplifier fpf:analyzer))
  163. ;;(define fpf:simplify (expression-simplifier fpf:analyzer))
  164. (define fpf:simplify
  165. (hash-memoize-1arg
  166. (compose canonical-copy
  167. (expression-simplifier fpf:analyzer))))
  168. (define pcf:analyzer
  169. (make-analyzer pcf:->expression pcf:expression-> pcf:operators-known))
  170. ;;(define pcf:simplify (default-simplifier pcf:analyzer))
  171. (define pcf:simplify (expression-simplifier pcf:analyzer))
  172. #|
  173. (define pcf:simplify
  174. (hash-memoize-1arg
  175. (compose canonical-copy
  176. (expression-simplifier pcf:analyzer))))
  177. |#
  178. (define rcf:analyzer
  179. (make-analyzer rcf:->expression rcf:expression-> rcf:operators-known))
  180. ;;(define rcf:simplify (default-simplifier rcf:analyzer))
  181. ;;(define rcf:simplify (expression-simplifier rcf:analyzer))
  182. (define rcf:simplify
  183. (hash-memoize-1arg
  184. (compose canonical-copy
  185. (expression-simplifier rcf:analyzer))))
  186. #|
  187. ((initializer rcf:analyzer))
  188. (pp ((expression-analyzer rcf:analyzer)
  189. '(- i (* Is (- (exp (/ (- v2 v3) Vt)) 1)))))
  190. (+ (* (+ 1 (* -1 kernel17)) Is) i)
  191. (pp ((auxiliary-variable-fetcher rcf:analyzer)))
  192. ((kernel17 (exp kernel16))
  193. (kernel16 (/ (+ v2 (* -1 v3)) Vt)))
  194. (pp ((expression-analyzer rcf:analyzer)
  195. '(exp (/ (- v3 v2) (- Vt)))))
  196. kernel17
  197. (pp ((expression-simplifier rcf:analyzer)
  198. '(- i (* Is (- (exp (/ (- v2 v3) Vt)) 1)))))
  199. (+ (* (+ 1 (* -1 (exp (/ (+ v2 (* -1 v3)) Vt)))) Is) i)
  200. ;Unspecified return value
  201. |#