zeros.scm 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. (declare (usual-integrations))
  21. ;;; To find x such that f(x)=0,
  22. ;;; given x1, x2 where f(x1) and f(x2) have opposite sign.
  23. (define (false-position-search f x1 x2 epsilon)
  24. (define (fpsl x1 fx1 x2 fx2)
  25. (let ((afx1 (abs fx1)) (afx2 (abs fx2)))
  26. (define (best-guess)
  27. (if (opposite-sign? fx1 fx2)
  28. (average x1 x2)
  29. (if (< afx1 afx2) x1 x2)))
  30. (if (< afx1 epsilon)
  31. (if (< afx2 epsilon)
  32. (best-guess)
  33. x1)
  34. (if (< afx2 epsilon)
  35. x2
  36. (if (close-enuf? x1 x2 epsilon)
  37. (best-guess)
  38. (let* ((x (/ (- (* x2 fx1) (* fx2 x1))
  39. (- fx1 fx2)))
  40. (fx (f x)))
  41. (if (opposite-sign? fx1 fx)
  42. (fpsl x1 fx1 x fx)
  43. (fpsl x fx x2 fx2))))))))
  44. (fpsl x1 (f x1) x2 (f x2)))
  45. #|
  46. ;;; For example
  47. (define (kepler ecc m)
  48. (false-position-search
  49. (lambda (e)
  50. (write-line e)
  51. (- e (* ecc (sin e)) m))
  52. 0.0
  53. 2pi
  54. 1e-15))
  55. (kepler .99 .01)
  56. 6.283185307179586
  57. 0.
  58. .01
  59. .01988423649613729
  60. 2.9653394755776365e-2
  61. 3.9307245802801455e-2
  62. .04884472750060591
  63. ;;; about 300 lines of iteration here
  64. .3422703164917564
  65. .34227031649175765
  66. .3422703164917588
  67. .3422703164917599
  68. ;Value: .3422703164917599
  69. |#
  70. ;;; If we are provided with a derivative of f as well as f
  71. ;;; we can try to converge faster with Newton's method.
  72. (define (newton-with-false-position-search f&df x1 x2 epsilon)
  73. (define (fpsl x1 fx1 dfx1 x2 fx2 dfx2)
  74. (define (try x)
  75. (if (opposite-sign? (- x x1) (- x x2))
  76. (begin ;;(write-line (list 'newton x1 fx1 dfx1 x2 fx2 dfx2 x))
  77. (next x))
  78. (begin ;;(write-line (list 'fp x1 fx1 x2 fx2))
  79. (next (/ (- (* x2 fx1) (* fx2 x1)) (- fx1 fx2))))))
  80. (define (next x)
  81. (f&df x
  82. (lambda (fx dfx)
  83. (if (opposite-sign? fx1 fx)
  84. (fpsl x1 fx1 dfx1 x fx dfx)
  85. (fpsl x fx dfx x2 fx2 dfx2)))))
  86. (let ((afx1 (abs fx1)) (afx2 (abs fx2)))
  87. (define (best-guess)
  88. (if (opposite-sign? fx1 fx2)
  89. (average x1 x2)
  90. (if (< afx1 afx2) x1 x2)))
  91. (if (< afx1 epsilon)
  92. (if (< afx2 epsilon)
  93. (best-guess)
  94. x1)
  95. (if (< afx2 epsilon)
  96. x2
  97. (if (close-enuf? x1 x2 epsilon)
  98. (best-guess)
  99. (if (< afx1 afx2)
  100. (try (- x1 (/ fx1 dfx1)))
  101. (try (- x2 (/ fx2 dfx2)))))))))
  102. (f&df x1
  103. (lambda (fx1 dfx1)
  104. (f&df x2
  105. (lambda (fx2 dfx2)
  106. (fpsl x1 fx1 dfx1 x2 fx2 dfx2))))))
  107. #|
  108. ;;; For example
  109. (define (kepler ecc m)
  110. (newton-with-false-position-search
  111. (lambda (e cont)
  112. (write-line e)
  113. (cont (- e (* ecc (sin e)) m)
  114. (- 1 (* ecc (cos e)))))
  115. 0.0
  116. 2pi
  117. 1e-15))
  118. (kepler .99 .01)
  119. .9999999999999991
  120. .05990042451486612
  121. .8552375430328689
  122. .12924052056093327
  123. .586704215814149
  124. .23257623307830544
  125. .3854635290318111
  126. .3463221490526433
  127. .34231027307859746
  128. .3422703204251508
  129. .34227031649177553
  130. ;Value 35: .34227031649177553
  131. |#
  132. (define (average x y)
  133. (/ (+ x y) 2.0))
  134. (define (opposite-sign? x y)
  135. (< (* x y) 0.0))