137 45 279MB
English Pages [1243]
The Mathematica GuideBook for Numerics
Michael Trott
The Mathematica GuideBook for Numerics
With 1364 Illustrations
Michael Trott Wolfram Research Champaign, Illinois
Mathematica is a registered trademark of Wolfram Research, Inc. Library of Congress Control Number: 2005928494 ISBN-10: 0-387-95011-7 ISBN-13: 978-0387-95011-2 e-ISBN 0-387-28814-7
Printed on acid-free paper.
© 2006 Springer Science+Business Media, Inc. All rights reserved. This work may not be translated or copied in whole or in part without the written permission of the publisher (Springer Science+Business Media, Inc., 233 Spring St., New York, NY 10013, USA), except for brief excerpts in connection with reviews or scholarly analysis. Use in connection with any form of information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed is forbidden. The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to proprietary rights. Printed in the United States of America. 9 8 7 6 5 4 3 2 1 springeronline.com
(HAM)
Preface Bei mathematischen Operationen kann sogar eine gänzliche Entlastung des Kopfes eintreten, indem man einmal ausgeführte Zähloperationen mit Zeichen symbolisiert und, statt die Hirnfunktion auf Wiederholung schon ausgeführter Operationen zu verschwenden, sie für wichtigere Fälle aufspart. When doing mathematics, instead of burdening the brain with the repetitive job of redoing numerical operations which have already been done before, it’s possible to save that brainpower for more important situations by using symbols, instead, to represent those numerical calculations. — Ernst Mach (1883 ) [45]
Computer Mathematics and Mathematica Computers were initially developed to expedite numerical calculations. A newer, and in the long run, very fruitful field is the manipulation of symbolic expressions. When these symbolic expressions represent mathematical entities, this field is generally called computer algebra [8]. Computer algebra begins with relatively elementary operations, such as addition and multiplication of symbolic expressions, and includes such things as factorization of integers and polynomials, exact linear algebra, solution of systems of equations, and logical operations. It also includes analysis operations, such as definite and indefinite integration, the solution of linear and nonlinear ordinary and partial differential equations, series expansions, and residue calculations. Today, with computer algebra systems, it is possible to calculate in minutes or hours the results that would (and did) take years to accomplish by paper and pencil. One classic example is the calculation of the orbit of the moon, which took the French astronomer Delaunay 20 years [12], [13], [14], [15], [11], [26], [27], [53], [16], [17], [25]. (The Mathematica GuideBooks cover the two other historic examples of calculations that, at the end of the 19th century, took researchers many years of hand calculations [1], [4], [38] and literally thousands of pages of paper.) Along with the ability to do symbolic calculations, four other ingredients of modern general-purpose computer algebra systems prove to be of critical importance for solving scientific problems: † a powerful high-level programming language to formulate complicated problems † programmable two- and three-dimensional graphics † robust, adaptive numerical methods, including arbitrary precision and interval arithmetic † the ability to numerically evaluate and symbolically deal with the classical orthogonal polynomials and special functions of mathematical physics. The most widely used, complete, and advanced general-purpose computer algebra system is Mathematica. Mathematica provides a variety of capabilities such as graphics, numerics, symbolics, standardized interfaces to other programs, a complete electronic document-creation environment (including a full-fledged mathematical typesetting system), and a variety of import and export capabilities. Most of these ingredients are necessary to coherently and exhaustively solve problems and model processes occurring in the natural sciences [41], [58], [21], [39] and other fields using constructive mathematics, as well as to properly represent the results. Conse-
Preface
vi
quently, Mathematica’s main areas of application are presently in the natural sciences, engineering, pure and applied mathematics, economics, finance, computer graphics, and computer science. Mathematica is an ideal environment for doing general scientific and engineering calculations, for investigating and solving many different mathematically expressable problems, for visualizing them, and for writing notes, reports, and papers about them. Thus, Mathematica is an integrated computing environment, meaning it is what is also called a “problem-solving environment” [40], [23], [6], [48], [43], [50], [52].
Scope and Goals The Mathematica GuideBooks are four independent books whose main focus is to show how to solve scientific problems with Mathematica. Each book addresses one of the four ingredients to solve nontrivial and real-life mathematically formulated problems: programming, graphics, numerics, and symbolics. The Programming and the Graphics volume were published in autumn 2004. The four Mathematica GuideBooks discuss programming, two-dimensional, and three-dimensional graphics, numerics, and symbolics (including special functions). While the four books build on each other, each one is self-contained. Each book discusses the definition, use, and unique features of the corresponding Mathematica functions, gives small and large application examples with detailed references, and includes an extensive set of relevant exercises and solutions. The GuideBooks have three primary goals: † to give the reader a solid working knowledge of Mathematica † to give the reader a detailed knowledge of key aspects of Mathematica needed to create the “best”, fastest, shortest, and most elegant solutions to problems from the natural sciences † to convince the reader that working with Mathematica can be a quite fruitful, enlightening, and joyful way of cooperation between a computer and a human. Realizing these goals is achieved by understanding the unifying design and philosophy behind the Mathematica system through discussing and solving numerous example-type problems. While a variety of mathematics and physics problems are discussed, the GuideBooks are not mathematics or physics books (from the point of view of content and rigor; no proofs are typically involved), but rather the author builds on Mathematica’s mathematical and scientific knowledge to explore, solve, and visualize a variety of applied problems. The focus on solving problems implies a focus on the computational engine of Mathematica, the kernel—rather than on the user interface of Mathematica, the front end. (Nevertheless, for a nicer presentation inside the electronic version, various front end features are used, but are not discussed in depth.) The Mathematica GuideBooks go far beyond the scope of a pure introduction into Mathematica. The books also present instructive implementations, explanations, and examples that are, for the most part, original. The books also discuss some “classical” Mathematica implementations, explanations, and examples, partially available only in the original literature referenced or from newsgroups threads. In addition to introducing Mathematica, the GuideBooks serve as a guide for generating fairly complicated graphics and for solving more advanced problems using graphical, numerical, and symbolical techniques in cooperative ways. The emphasis is on the Mathematica part of the solution, but the author employs examples that are not uninteresting from a content point of view. After studying the GuideBooks, the reader will be able to solve new and old scientific, engineering, and recreational mathematics problems faster and more completely with the help of Mathematica—at least, this is the author’s goal. The author also hopes that the reader will enjoy
Preface
vii
using Mathematica for visualization of the results as much as the author does, as well as just studying Mathematica as a language on its own. In the same way that computer algebra systems are not “proof machines” [46], [9], [37], [10], [54], [55], [56] such as might be used to establish the four-color theorem ([2], [22]), the Kepler [28], [19], [29], [30], [31], [32], [33], [34], [35], [36] or the Robbins ([44], [20]) conjectures, proving theorems is not the central theme of the GuideBooks. However, powerful and general proof machines [9], [42], [49], [24], [3], founded on Mathematica’ s general programming paradigms and its mathematical capabilities, have been built (one such system is Theorema [7]). And, in the GuideBooks, we occasionally prove one theorem or another theorem. In general, the author’s aim is to present a realistic portrait of Mathematica: its use, its usefulness, and its strengths, including some current weak points and sometimes unexpected, but often nevertheless quite “thought through”, behavior. Mathematica is not a universal tool to solve arbitrary problems which can be formulated mathematically—only a fraction of all mathematical problems can even be formulated in such a way to be efficiently expressed today in a way understandable to a computer. Rather, it is often necessary to do a certain amount of programming and occasionally give Mathematica some “help” instead of simply calling a single function like Solve to solve a system of equations. Because this will almost always be the case for “real-life” problems, we do not restrict ourselves only to “textbook” examples, where all goes smoothly without unexpected problems and obstacles. The reader will see that by employing Mathematica’s programming, numeric, symbolic, and graphic power, Mathematica can offer more effective, complete, straightforward, reusable, and less likely erroneous solution methods for calculations than paper and pencil, or numerical programming languages. Although the Guidebooks are large books, it is nevertheless impossible to discuss all of the 2,000+ built-in Mathematica commands. So, some simple as well as some more complicated commands have been omitted. For a full overview about Mathematica’s capabilities, it is necessary to study The Mathematica Book [60] in detail. The commands discussed in the Guidebooks are those that an scientist or research engineer needs for solving typical problems, if such a thing exists [18]. These subjects include a quite detailed discussion of the structure of Mathematica expressions, Mathematica input and output (important for the human–Mathematica interaction), graphics, numerical calculations, and calculations from classical analysis. Also, emphasis is given to the powerful algebraic manipulation functions. Interestingly, they frequently allow one to solve analysis problems in an algorithmic way [5]. These functions are typically not so well known because they are not taught in classical engineering or physics-mathematics courses, but with the advance of computers doing symbolic mathematics, their importance increases [47]. A thorough knowledge of: † machine and high-precision numbers, packed arrays, and intervals † machine, high-precision, and interval arithmetic † process of compilation, its advantages and limits † main operations of numerical analysis, such as equation solving, minimization, summation † numerical solution of ordinary and partial differential equations is needed for virtually any nontrivial numeric calculation and frequently also in symbolic computations. The Mathematica GuideBook for Numerics discusses these subjects. The current version of the Mathematica GuideBooks is tailored for Mathematica Version 5.1.
viii
Preface
Content Overview The Mathematica GuideBook for Numerics has two chapters. Each chapter is subdivided into sections (which occasionally have subsections), exercises, solutions to the exercises, and references. This volume deals with Mathematica’s numerical mathematics capabilities, the indispensable tools for dealing with virtually any “real life” problem. Fast machine, exact integer, and rational and verified high-precision arithmetic is applied to a large number of examples in the main text and in the solutions to the exercises. Chapter 1 deals with numerical calculations, which are important for virtually all Mathematica users. This volume starts with calculations involving real and complex numbers with an “arbitrary” number of digits. (Well, not really an "arbitrary" number of digits, but on present-day computers, many calculations involving a few million digits are easily feasible.). Then follows a discussion of significance arithmetic, which automatically keeps track of the digits which are correct in calculations with high-precision numbers. Also discussed is the use of interval arithmetic. (Despite being slow, exact and/or inexact, interval arithmetic allows one to carry out validated numerical calculations.) The next important subject is the (pseudo)compilation of Mathematica code. Because Mathematica is an interpreted language that allows for “unforeseeable” actions and arbitrary side effects at runtime, it generally cannot be compiled. Strictly numerical calculations can, of course, be compiled. Then, the main numerical functions are discussed: interpolation, Fourier transforms, numerical summation, and integration, solution of equations (root finding), minimization of functions, and the solution of ordinary and partial differential equations. To illustrate Mathematica’s differential equation solving capabilities, many ODEs and PDEs are discussed. Many medium-sized examples are given for the various numerical procedures. In addition, Mathematica is used to monitor and visualize various numerical algorithms. The main part of Chapter 1 culminates with two larger applications, the construction of Riemann surfaces of algebraic functions and the visualization of electric and magnetic field lines of some more complicated two- and three-dimensional charge and current distributions. A large, diverse set of exercises and detailed solutions ends the first chapter. Chapter 2 deals with exact integer calculations and integer-valued functions while concentrating on topics that are important in classical analysis. Number theory functions and modular polynomial functions, currently little used in most natural science applications, are intentionally given less detailed treatment. While some of the functions of this chapter have analytic continuations to complex arguments and could so be considered as belonging to Chapter 3 of the Symbolics volume, emphasis is given to their combinatorial use in this chapter. This volume explains and demonstrates the use of the numerical functions of Mathematica. It only rarely discusses the underlying numerical algorithms themselves. But occasionally Mathematica is used to monitor how the algorithms work and progress.
The Books and the Accompanying DVDs Each of the GuideBooks comes with a multiplatform DVD. Each DVD contains the fourteen main notebooks, the hyperlinked table of contents and index, a navigation palette, and some utility notebooks and files. All notebooks are tailored for Mathematica 5.1. Each of the main notebooks corresponds to a chapter from the printed books. The notebooks have the look and feel of a printed book, containing structured units, typeset formulas, Mathemat-
Preface
ix
ica code, and complete solutions to all exercises. The DVDs contain the fully evaluated notebooks corresponding to the chapters of the corresponding printed book (meaning these notebooks have text, inputs, outputs and graphics). The DVDs also include the unevaluated versions of the notebooks of the other three GuideBooks (meaning they contain all text and Mathematica code, but no outputs and graphics). Although the Mathematica GuideBooks are printed, Mathematica is “a system for doing mathematics by computer” [59]. This was the lovely tagline of earlier versions of Mathematica, but because of its growing breadth (like data import, export and handling, operating system-independent file system operations, electronic publishing capabilities, web connectivity), nowadays Mathematica is called a “system for technical computing”. The original tagline (that is more than ever valid today!) emphasized two points: doing mathematics and doing it on a computer. The approach and content of the GuideBooks are fully in the spirit of the original tagline: They are centered around doing mathematics. The second point of the tagline expresses that an electronic version of the GuideBooks is the more natural medium for Mathematica-related material. Long outputs returned by Mathematica, sequences of animations, thousands of web-retrievable references, a 10,000-entry hyperlinked index (that points more precisely than a printed index does) are space-consuming, and therefore not well suited for the printed book. As an interactive program, Mathematica is best learned, used, challenged, and enjoyed while sitting in front of a powerful computer (or by having a remote kernel connection to a powerful computer). In addition to simply showing the printed book’s text, the notebooks allow the reader to: † experiment with, reuse, adapt, and extend functions and code † investigate parameter dependencies † annotate text, code, and formulas † view graphics in color † run animations.
The Accompanying Web Site Why does a printed book need a home page? There are (in addition to being just trendy) two reasons for a printed book to have its fingerprints on the web. The first is for (Mathematica) users who have not seen the book so far. Having an outline and content sample on the web is easily accomplished, and shows the look and feel of the notebooks (including some animations). This is something that a printed book actually cannot do. The second reason is for readers of the book: Mathematica is a large modern software system. As such, it ages quickly in the sense that in the timescale of 101. smallIntegermonths, a new version will likely be available. The overwhelmingly large majority of Mathematica functions and programs will run unchanged in a new version. But occasionally, changes and adaptations might be needed. To accommodate this, the web site of this book—http://www.MathematicaGuideBooks.org—contains a list of changes relevant to the GuideBooks. In addition, like any larger software project, unavoidably, the GuideBooks will contain suboptimal implementations, mistakes, omissions, imperfections, and errors. As they come to his attention, the author will list them at the book’s web site. Updates to references, corrections [51], hundreds of pages of additional exercises and solutions, improved code segments, and other relevant information will be on the web site as well. Also, information about OS-dependent and Mathematica version-related changes of the given Mathematica code will be available there.
Preface
x
Evolution of the Mathematica GuideBooks A few words about the history and the original purpose of the GuideBooks: They started from lecture notes of an Introductory Course in Mathematica 2 and an advanced course on the Efficient Use of the Mathematica Programming System, given in 1991/1992 at the Technical University of Ilmenau, Germany. Since then, after each release of a new version of Mathematica, the material has been updated to incorporate additional functionality. This electronic/printed publication contains text, unique graphics, editable formulas, runable, and modifiable programs, all made possible by the electronic publishing capabilities of Mathematica. However, because the structure, functions and examples of the original lecture notes have been kept, an abbreviated form of the GuideBooks is still suitable for courses. Since 1992 the manuscript has grown in size from 1,600 pages to more than three times its original length, finally “weighing in” at nearly 5,000 printed book pages with more than: † 18 gigabytes of accompanying Mathematica notebooks † 22,000 Mathematica inputs with more than 13,000 code comments † 11,000 references † 4,000 graphics † 1,000 fully solved exercises † 150 animations. This first edition of this book is the result of more than eleven years of writing and daily work with Mathematica. In these years, Mathematica gained hundreds of functions with increased functionality and power. A modern year-2005 computer equipped with Mathematica represents a computational power available only a few years ago to a select number of people [57] and allows one to carry out recreational or new computations and visualizations—unlimited in nature, scope, and complexity— quickly and easily. Over the years, the author has learned a lot of Mathematica and its current and potential applications, and has had a lot of fun, enlightening moments and satisfaction applying Mathematica to a variety of research and recreational areas, especially graphics. The author hopes the reader will have a similar experience.
Disclaimer In addition to the usual disclaimer that neither the author nor the publisher guarantees the correctness of any formula, fitness, or reliability of any of the code pieces given in this book, another remark should be made. No guarantee is given that running the Mathematica code shown in the GuideBooks will give identical results to the printed ones. On the contrary, taking into account that Mathematica is a large and complicated software system which evolves with each released version, running the code with another version of Mathematica (or sometimes even on another operating system) will very likely result in different outputs for some inputs. And, as a consequence, if different outputs are generated early in a longer calculation, some functions might hang or return useless results. The interpretations of Mathematica commands, their descriptions, and uses belong solely to the author. They are not claimed, supported, validated, or enforced by Wolfram Research. The reader will find that the author’s view on Mathematica deviates sometimes considerably from those found in other books. The author’s view is more on
Preface
xi
the formal than on the pragmatic side. The author does not hold the opinion that any Mathematica input has to have an immediate semantic meaning. Mathematica is an extremely rich system, especially from the language point of view. It is instructive, interesting, and fun to study the behavior of built-in Mathematica functions when called with a variety of arguments (like unevaluated, hold, including undercover zeros, etc.). It is the author’s strong belief that doing this and being able to explain the observed behavior will be, in the long term, very fruitful for the reader because it develops the ability to recognize the uniformity of the principles underlying Mathematica and to make constructive, imaginative, and effective use of this uniformity. Also, some exercises ask the reader to investigate certain “unusual” inputs. From time to time, the author makes use of undocumented features and/or functions from the Developer` and Experimental` contexts (in later versions of Mathematica these functions could exist in the System` context or could have different names). However, some such functions might no longer be supported or even exist in later versions of Mathematica.
Acknowledgements Over the decade, the GuideBooks were in development, many people have seen parts of them and suggested useful changes, additions, and edits. I would like to thank Horst Finsterbusch, Gottfried Teichmann, Klaus Voss, Udo Krause, Jerry Keiper, David Withoff, and Yu He for their critical examination of early versions of the manuscript and their useful suggestions, and Sabine Trott for the first proofreading of the German manuscript. I also want to thank the participants of the original lectures for many useful discussions. My thanks go to the reviewers of this book: John Novak, Alec Schramm, Paul Abbott, Jim Feagin, Richard Palmer, Ward Hanson, Stan Wagon, and Markus van Almsick, for their suggestions and ideas for improvement. I thank Richard Crandall, Allan Hayes, Andrzej Kozlowski, Hartmut Wolf, Stephan Leibbrandt, George Kambouroglou, Domenico Minunni, Eric Weisstein, Andy Shiekh, Arthur G. Hubbard, Jay Warrendorff, Allan Cortzen, Ed Pegg, and Udo Krause for comments on the prepublication version of the GuideBooks. I thank Bobby R. Treat, Arthur G. Hubbard, Murray Eisenberg, Marvin Schaefer, Marek Duszynski, Daniel Lichtblau, Devendra Kapadia, Adam Strzebonski, Anton Antonov, and Brett Champion for useful comments on the Mathematica Version 5.1 tailored version of the GuideBooks. My thanks are due to Gerhard Gobsch of the Institute for Physics of the Technical University in Ilmenau for the opportunity to develop and give these original lectures at the Institute, and to Stephen Wolfram who encouraged and supported me on this project. Concerning the process of making the Mathematica GuideBooks from a set of lecture notes, I thank Glenn Scholebo for transforming notebooks to T E X files, and Joe Kaiping for T E X work related to the printed book. I thank John Novak and Jan Progen for putting all the material into good English style and grammar, John Bonadies for the chapter-opener graphics of the book, and Jean Buck for library work. I especially thank John Novak for the creation of Mathematica 3 notebooks from the T E X files, and Andre Kuzniarek for his work on the stylesheet to give the notebooks a pleasing appearance. My thanks go to Andy Hunt who created a specialized stylesheet for the actual book printout and printed and formatted the 4×1000+ pages of the Mathematica GuideBooks. I thank Andy Hunt for making a first version of the homepage of the GuideBooks and Amy Young for creating the current version of the homepage of the GuideBooks. I thank Sophie Young for a final check of the English. My largest thanks go to Amy Young, who encouraged me to update the whole book over the years and who had a close look at all of my English writing and often improved it considerably. Despite reviews by many individuals any remaining mistakes or omissions, in the Mathematica code, in the mathematics, in the description of the Mathematica functions, in the English, or in the references, etc. are, of course, solely mine.
xii
Preface
Let me take the opportunity to thank members of the Research and Development team of Wolfram Research whom I have met throughout the years, especially Victor Adamchik, Anton Antonov, Alexei Bocharov, Arnoud Buzing, Brett Champion, Matthew Cook, Todd Gayley, Darren Glosemeyer, Roger Germundsson, Unal Goktas, Yifan Hu, Devendra Kapadia, Zbigniew Leyk, David Librik, Daniel Lichtblau, Jerry Keiper, Robert Knapp, Roman Mäder, Oleg Marichev, John Novak, Peter Overmann, Oleksandr Pavlyk, Ulises Cervantes–Pimentel, Mark Sofroniou, Adam Strzebonski, Oyvind Tafjord, Robby Villegas, Tom Wickham–Jones, David Withoff, and Stephen Wolfram for numerous discussions about design principles, various small details, underlying algorithms, efficient implementation of various procedures, and tricks concerning Mathematica. The appearance of the notebooks profited from discussions with John Fultz, Paul Hinton, John Novak, Lou D’Andria, Theodore Gray, Andre Kuzniarek, Jason Harris, Andy Hunt, Christopher Carlson, Robert Raguet–Schofield, George Beck, Kai Xin, Chris Hill, and Neil Soiffer about front end, button, and typesetting issues. I'm grateful to Jeremy Hilton from the Corporation for National Research Initiatives for allowing the use of the text of Shakespeare's Hamlet (to be used in Chapter 1 of The Mathematica GuideBook to Numerics). It was an interesting and unique experience to work over the last 12 years with five editors: Allan Wylde, Paul Wellin, Maria Taylor, Wayne Yuhasz, and Ann Kostant, with whom the GuideBooks were finally published. Many book-related discussions that ultimately improved the GuideBooks, have been carried out with Jan Benes from TELOS and associates, Steven Pisano, Jenny Wolkowicki, Henry Krell, Fred Bartlett, Vaishali Damle, Ken Quinn, Jerry Lyons, and Rüdiger Gebauer from Springer New York. The author hopes the Mathematica GuideBooks help the reader to discover, investigate, urbanize, and enjoy the computational paradise offered by Mathematica.
Wolfram Research, Inc. April 2005
Michael Trott
Preface
xiii
References 1
A. Amthor. Z. Math. Phys. 25, 153 (1880).
2
K. Appel, W. Haken. J. Math. 21, 429 (1977).
3
A. Bauer, E. Clarke, X. Zhao. J. Automat. Reasoning 21, 295 (1998).
4
A. H. Bell. Am. Math. Monthly 2, 140 (1895).
5
M. Berz. Adv. Imaging Electron Phys. 108, 1 (2000).
6
R. F. Boisvert. arXiv:cs.MS/0004004 (2000).
7
B. Buchberger. Theorema Project (1997). ftp://ftp.risc.uni-linz.ac.at/pub/techreports/1997/97-34/ed-media.nb
8
B. Buchberger. SIGSAM Bull. 36, 3 (2002).
9
S.-C. Chou, X.-S. Gao, J.-Z. Zhang. Machine Proofs in Geometry, World Scientific, Singapore, 1994.
10
A. M. Cohen. Nieuw Archief Wiskunde 14, 45 (1996).
11
A. Cook. The Motion of the Moon, Adam-Hilger, Bristol, 1988.
12
C. Delaunay. Théorie du Mouvement de la Lune, Gauthier-Villars, Paris, 1860.
13
C. Delaunay. Mem. de l’ Acad. des Sc. Paris 28 (1860).
14
C. Delaunay. Mem. de l’ Acad. des Sc. Paris 29 (1867).
15
A. Deprit, J. Henrard, A. Rom. Astron. J. 75, 747 (1970).
16
A. Deprit. Science 168, 1569 (1970).
17
A. Deprit, J. Henrard, A. Rom. Astron. J. 76, 273 (1971).
18
P. J. Dolan, Jr., D. S. Melichian. Am. J. Phys. 66, 11 (1998).
19
S. P. Ferguson, T. C. Hales. arXiv:math.MG/ 9811072 (1998).
20
B. Fitelson. Mathematica Educ. Res. 7, n1, 17 (1998).
21
A. C. Fowler. Mathematical Models in the Applied Sciences, Cambridge University Press, Cambridge, 1997.
22
H. Fritsch, G. Fritsch. The Four-Color Theorem, Springer-Verlag, New York, 1998.
23
E. Gallopoulus, E. Houstis, J. R. Rice (eds.). Future Research Directions in Problem Solving Environments for Computational Science: Report of a Workshop on Research Directions in Integrating Numerical Analysis, Symbolic Computing, Computational Geometry, and Artificial Intelligence for Computational Science, 1991. http://www.cs.purdue.edu/research/cse/publications/tr/92/92-032.ps.gz
24
V. Gerdt, S. A. Gogilidze in V. G. Ganzha, E. W. Mayr, E. V. Vorozhtsov (eds.). Computer Algebra in Scientific Computing, Springer-Verlag, Berlin, 1999.
25
M. C. Gutzwiller, D. S. Schmidt. Astronomical Papers: The Motion of the Moon as Computed by the Method of Hill, Brown, and Eckert, U.S. Government Printing Office, Washington, 1986.
26
M. C. Gutzwiller. Rev. Mod. Phys. 70, 589 (1998).
27
Y. Hagihara. Celestial Mechanics vII/1, MIT Press, Cambridge, 1972.
28
T. C. Hales. arXiv:math.MG/ 9811071 (1998).
29
T. C. Hales. arXiv:math.MG/ 9811073 (1998).
30
T. C. Hales. arXiv:math.MG/ 9811074 (1998).
31
T. C. Hales. arXiv:math.MG/ 9811075 (1998).
32
T. C. Hales. arXiv:math.MG/ 9811076 (1998).
33
T. C. Hales. arXiv:math.MG/ 9811077 (1998).
Preface
xiv 34
T. C. Hales. arXiv:math.MG/ 9811078 (1998).
35
T. C. Hales. arXiv:math.MG/0205208 (2002).
36
T. C. Hales in L. Tatsien (ed.). Proceedings of the International Congress of Mathematicians v. 3, Higher Education Press, Beijing, 2002.
37
J. Harrison. Theorem Proving with the Real Numbers, Springer-Verlag, London, 1998.
38
J. Hermes. Nachrichten Königl. Gesell. Wiss. Göttingen 170 (1894).
39 40
E. N. Houstis, J. R. Rice, E. Gallopoulos, R. Bramley (eds.). Enabling Technologies for Computational Science, Kluwer, Boston, 2000. E. N. Houstis, J. R. Rice. Math. Comput. Simul. 54, 243 (2000).
41
M. S. Klamkin (eds.). Mathematical Modelling, SIAM, Philadelphia, 1996.
42
H. Koch, A. Schenkel, P. Wittwer. SIAM Rev. 38, 565 (1996).
43
Y. N. Lakshman, B. Char, J. Johnson in O. Gloor (ed.). ISSAC 1998, ACM Press, New York, 1998.
44
W. McCune. Robbins Algebras Are Boolean, 1997. http://www.mcs.anl.gov/home/mccune/ar/robbins/
45 46
E. Mach (R. Wahsner, H.-H. von Borszeskowski eds.). Die Mechanik in ihrer Entwicklung, Akademie-Verlag, Berlin, 1988. D. A. MacKenzie. Mechanizing Proof: Computing, Risk, and Trust, MIT Press, Cambridge, 2001.
47
B. M. McCoy. arXiv:cond-mat/0012193 (2000).
48
K. J. M. Moriarty, G. Murdeshwar, S. Sanielevici. Comput. Phys. Commun. 77, 325 (1993).
49
I. Nemes, M. Petkovšek, H. S. Wilf, D. Zeilberger. Am. Math. Monthly 104, 505 (1997).
50
W. H. Press, S. A. Teukolsky. Comput. Phys. 11, 417 (1997).
51
D. Rawlings. Am. Math. Monthly 108, 713 (2001).
52
Problem Solving Environments Home Page. http://www.cs.purdue.edu/research/cse/pses
53 54
D. S. Schmidt in H. S. Dumas, K. R. Meyer, D. S. Schmidt (eds.). Hamiltonian Dynamical Systems, Springer-Verlag, New York, 1995. S. Seiden. SIGACT News 32, 111 (2001).
55
S. Seiden. Theor. Comput. Sc. 282, 381 (2002).
56
C. Simpson. arXiv:math.HO/0311260 (2003).
57
A. M. Stoneham. Phil. Trans. R. Soc. Lond. A 360, 1107 (2002).
58
M. Tegmark. Ann. Phys. 270, 1 (1999).
59
S. Wolfram. Mathematica: A System for Doing Mathematics by Computer, Addison-Wesley, Redwood City, 1992.
60
S. Wolfram. The Mathematica Book, Wolfram Media, Champaign, 2003.
Contents 0.
Introduction and Orientation xvii
CHAPTER 1
Numerical Computations 1.0
Remarks 1
1.1
Approximate Numbers 15 1.1.0 Remarks 15 1.1.1
Numbers with an Arbitrary Number of Digits 15
1.1.2
Interval Arithmetic 54
1.1.3
Converting Approximate Numbers to Exact Numbers 66
1.1.4
When N Does Not Succeed 94
1.1.5
Packed Arrays 101
1.2
Fitting and Interpolating Functions 124
1.3
Compiled Programs 159
1.4
Linear Algebra 203
1.5
Fourier Transforms 225
1.6
Numerical Functions and Their Options 264
1.7
Sums and Products 272
1.8
Integration 289
1.9
Solution of Equations 316
1.10
Minimization 347
1.11
Solution of Differential Equations 368 1.11.1 Ordinary Differential Equations 368 1.11.2
Partial Differential Equations 451
xvi 1.12
Two Applications 481 1.12.0 Remarks 481 1.12.1
Visualizing Electric and Magnetic Field Lines 481
1.12.2
Riemann Surfaces of Algebraic Functions 508
Exercises 521 Solutions 703 References 915
CHAPTER 2
Computations with Exact Numbers 2.0
Remarks 969
2.1
Divisors and Multiples 974
2.2
Number Theory Functions 1009
2.3
Combinatorial Functions 1030
2.4
Euler, Bernoulli, and Fibonacci Numbers 1046 Exercises 1060 Solutions 1076 References 1173 Index 1191
Introduction and Orientation to The Mathematica GuideBooks 0.1 Overview 0.1.1 Content Summaries The Mathematica GuideBooks are published as four independent books: The Mathematica GuideBook to Programming, The Mathematica GuideBook to Graphics, The Mathematica GuideBook to Numerics, and The Mathematica GuideBook to Symbolics. † The Programming volume deals with the structure of Mathematica expressions and with Mathematica as a programming language. This volume includes the discussion of the hierarchical construction of all Mathematica objects out of symbolic expressions (all of the form head[argument]), the ultimate building blocks of expressions (numbers, symbols, and strings), the definition of functions, the application of rules, the recognition of patterns and their efficient application, the order of evaluation, program flows and program structure, the manipulation of lists (the universal container for Mathematica expressions of all kinds), as well as a number of topics specific to the Mathematica programming language. Various programming styles, especially Mathematica’ s powerful functional programming constructs, are covered in detail. † The Graphics volume deals with Mathematica’s two-dimensional (2D) and three-dimensional (3D) graphics. The chapters of this volume give a detailed treatment on how to create images from graphics primitives, such as points, lines, and polygons. This volume also covers graphically displaying functions given either analytically or in discrete form. A number of images from the Mathematica Graphics Gallery are also reconstructed. Also discussed is the generation of pleasing scientific visualizations of functions, formulas, and algorithms. A variety of such examples are given. † The Numerics volume deals with Mathematica’s numerical mathematics capabilities—the indispensable sledgehammer tools for dealing with virtually any “real life” problem. The arithmetic types (fast machine, exact integer and rational, verified high-precision, and interval arithmetic) are carefully analyzed. Fundamental numerical operations, such as compilation of programs, numerical Fourier transforms, minimization, numerical solution of equations, and ordinary/partial differential equations are analyzed in detail and are applied to a large number of examples in the main text and in the solutions to the exercises. † The Symbolics volume deals with Mathematica’s symbolic mathematical capabilities—the real heart of Mathematica and the ingredient of the Mathematica software system that makes it so unique and powerful. Structural and mathematical operations on systems of polynomials are fundamental to many symbolic calculations and are covered in detail. The solution of equations and differential equations, as well as the classical calculus operations, are exhaustively treated. In addition, this volume discusses and employs the classical
xviii
Introduction
orthogonal polynomials and special functions of mathematical physics. To demonstrate the symbolic mathematics power, a variety of problems from mathematics and physics are discussed. The four GuideBooks contain about 25,000 Mathematica inputs, representing more than 75,000 lines of commented Mathematica code. (For the reader already familiar with Mathematica, here is a more precise measure: The LeafCount of all inputs would be about 900,000 when collected in a list.) The GuideBooks also have more than 4,000 graphics, 150 animations, 11,000 references, and 1,000 exercises. More than 10,000 hyperlinked index entries and hundreds of hyperlinks from the overview sections connect all parts in a convenient way. The evaluated notebooks of all four volumes have a cumulative file size of about 20 GB. Although these numbers may sound large, the Mathematica GuideBooks actually cover only a portion of Mathematica’s functionality and features and give only a glimpse into the possibilities Mathematica offers to generate graphics, solve problems, model systems, and discover new identities, relations, and algorithms. The Mathematica code is explained in detail throughout all chapters. More than 13,000 comments are scattered throughout all inputs and code fragments.
0.1.2 Relation of the Four Volumes The four volumes of the GuideBooks are basically independent, in the sense that readers familiar with Mathematica programming can read any of the other three volumes. But a solid working knowledge of the main topics discussed in The Mathematica GuideBook to Programming—symbolic expressions, pure functions, rules and replacements, and list manipulations—is required for the Graphics, Numerics, and Symbolics volumes. Compared to these three volumes, the Programming volume might appear to be a bit “dry”. But similar to learning a foreign language, before being rewarded with the beauty of novels or a poem, one has to sweat and study. The whole suite of graphical capabilities and all of the mathematical knowledge in Mathematica are accessed and applied through lists, patterns, rules, and pure functions, the material discussed in the Programming volume. Naturally, graphics are the center of attention of the The Mathematica GuideBook to Graphics. While in the Programming volume some plotting and graphics for visualization are used, graphics are not crucial for the Programming volume. The reader can safely skip the corresponding inputs to follow the main programming threads. The Numerics and Symbolics volumes, on the other hand, make heavy use of the graphics knowledge acquired in the Graphics volume. Hence, the prerequisites for the Numerics and Symbolics volumes are a good knowledge of Mathematica’s programming language and of its graphics system. The Programming volume contains only a few percent of all graphics, the Graphics volume contains about two-thirds, and the Numerics and Symbolics volume, about one-third of the overall 4,000+ graphics. The Programming and Graphics volumes use some mathematical commands, but they restrict the use to a relatively small number (especially Expand, Factor, Integrate, Solve). And the use of the function N for numerical ization is unavoidable for virtually any “real life” application of Mathematica. The last functions allow us to treat some mathematically not uninteresting examples in the Programming and Graphics volumes. In addition to putting these functions to work for nontrivial problems, a detailed discussion of the mathematics functions of Mathematica takes place exclusively in the Numerics and Symbolics volumes. The Programming and Graphics volumes contain a moderate amount of mathematics in the examples and exercises, and focus on programming and graphics issues. The Numerics and Symbolics volumes contain a substantially larger amount of mathematics. Although printed as four books, the fourteen individual chapters (six in the Programming volume, three in the Graphics volume, two in the Numerics volume, and three in the Symbolics volume) of the Mathematica GuideBooks form one organic whole, and the author recommends a strictly sequential reading, starting from Chapter 1 of the Programming volume and ending with Chapter 3 of the Symbolics volume for gaining the maximum
Introduction
xix
benefit. The electronic component of each book contains the text and inputs from all the four GuideBooks, together with a comprehensive hyperlinked index. The four volumes refer frequently to one another.
0.1.3 Chapter Structure A rough outline of the content of a chapter is the following: † The main body discusses the Mathematica functions belonging to the chapter subject, as well their options and attributes. Generically, the author has attempted to introduce the functions in a “natural order”. But surely, one cannot be axiomatic with respect to the order. (Such an order of the functions is not unique, and the author intentionally has “spread out” the introduction of various Mathematica functions across the four volumes.) With the introduction of a function, some small examples of how to use the functions and comparisons of this function with related ones are given. These examples typically (with the exception of some visualizations in the Programming volume) incorporate functions already discussed. The last section of a chapter often gives a larger example that makes heavy use of the functions discussed in the chapter. † A programmatically constructed overview of each chapter functions follows. The functions listed in this section are hyperlinked to their attributes and options, as well as to the corresponding reference guide entries of The Mathematica Book. † A set of exercises and potential solutions follow. Because learning Mathematica through examples is very efficient, the proposed solutions are quite detailed and form up to 50% of the material of a chapter. † References end the chapter. Note that the first few chapters of the Programming volume deviate slightly from this structure. Chapter 1 of the Programming volume gives a general overview of the kind of problems dealt with in the four GuideBooks. The second, third, and fourth chapters of the Programming volume introduce the basics of programming in Mathematica. Starting with Chapters 5 of the Programming volume and throughout the Graphics, Numerics, and Symbolics volumes, the above-described structure applies. In the 14 chapters of the GuideBooks the author has chosen a “we” style for the discussions of how to proceed in constructing programs and carrying out calculations to include the reader intimately.
0.1.4 Code Presentation Style The typical style of a unit of the main part of a chapter is: Define a new function, discuss its arguments, options, and attributes, and then give examples of its usage. The examples are virtually always Mathematica inputs and outputs. The majority of inputs is in InputForm are the notebooks. On occasion StandardForm is also used. Although StandardForm mimics classical mathematics notation and makes short inputs more readable, for “program-like” inputs, InputForm is typically more readable and easier and more natural to align. For the outputs, StandardForm is used by default and occasionally the author has resorted to InputForm or FullForm to expose digits of numbers and to TraditionalForm for some formulas. Outputs are mostly not programs, but nearly always “results” (often mathematical expressions, formulas, identities, or lists of numbers rather than program constructs). The world of Mathematica users is divided into three groups, and each of them has a nearly religious opinion on how to format Mathematica code [1], [2]. The author follows the InputForm
xx
Introduction
cult(ure) and hopes that the Mathematica users who do everything in either StandardForm or Tradition alForm will bear with him. If the reader really wants to see all code in either StandardForm or Tradition alForm, this can easily be done with the Convert To item from the Cell menu. (Note that the relation between InputForm and StandardForm is not symmetric. The InputForm cells of this book have been line-broken and aligned by hand. Transforming them into StandardForm or TraditionalForm cells works well because one typically does not line-break manually and align Mathematica code in these cell types. But converting StandardForm or TraditionalForm cells into InputForm cells results in much less pleasing results.) In the inputs, special typeset symbols for Mathematica functions are typically avoided because they are not monospaced. But the author does occasionally compromise and use Greek, script, Gothic, and doublestruck characters. In a book about a programming language, two other issues come always up: indentation and placement of the code. † The code of the GuideBooks is largely consistently formatted and indented. There are no strict guidelines or even rules on how to format and indent Mathematica code. The author hopes the reader will find the book’s formatting style readable. It is a compromise between readability (mental parsabililty) and space conservation, so that the printed version of the Mathematica GuideBook matches closely the electronic version. † Because of the large number of examples, a rather imposing amount of Mathematica code is presented. Should this code be present only on the disk, or also in the printed book? If it is in the printed book, should it be at the position where the code is used or at the end of the book in an appendix? Many authors of Mathematica articles and books have strong opinions on this subject. Because the main emphasis of the Mathematica GuideBooks is on solving problems with Mathematica and not on the actual problems, the GuideBooks give all of the code at the point where it is needed in the printed book, rather than “hiding” it in packages and appendices. In addition to being more straightforward to read and conveniently allowing us to refer to elements of the code pieces, this placement makes the correspondence between the printed book and the notebooks close to 1:1, and so working back and forth between the printed book and the notebooks is as straightforward as possible.
0.2 Requirements 0.2.1 Hardware and Software Throughout the GuideBooks, it is assumed that the reader has access to a computer running a current version of Mathematica (version 5.0/5.1 or newer). For readers without access to a licensed copy of Mathematica, it is possible to view all of the material on the disk using a trial version of Mathematica. (A trial version is downloadable from http://www.wolfram.com/products/mathematica/trial.cgi.) The files of the GuideBooks are relatively large, altogether more than 20 GB. This is also the amount of hard disk space needed to store uncompressed versions of the notebooks. To view the notebooks comfortably, the reader’s computer needs 128 MB RAM; to evaluate the evaluation units of the notebooks 1 GB RAM or more is recommended. In the GuideBooks, a large number of animations are generated. Although they need more memory than single pictures, they are easy to create, to animate, and to store on typical year-2005 hardware, and they provide a lot of joy.
Introduction
xxi
0.2.2 Reader Prerequisites Although prior Mathematica knowledge is not needed to read The Mathematica GuideBook to Programming, it is assumed that the reader is familiar with basic actions in the Mathematica front end, including entering Greek characters using the keyboard, copying and pasting cells, and so on. Freely available tutorials on these (and other) subjects can be found at http://library.wolfram.com. For a complete understanding of most of the GuideBooks examples, it is desirable to have a background in mathematics, science, or engineering at about the bachelor’s level or above. Familiarity with mechanics and electrodynamics is assumed. Some examples and exercises are more specialized, for instance, from quantum mechanics, finite element analysis, statistical mechanics, solid state physics, number theory, and other areas. But the GuideBooks avoid very advanced (but tempting) topics such as renormalization groups [6], parquet approximations [27], and modular moonshines [14]. (Although Mathematica can deal with such topics, they do not fit the character of the Mathematica GuideBooks but rather the one of a Mathematica Topographical Atlas [a monumental work to be carried out by the Mathematica–Bourbakians of the 21st century]). Each scientific application discussed has a set of references. The references should easily give the reader both an overview of the subject and pointers to further references.
0.3 What the GuideBooks Are and What They Are Not 0.3.1 Doing Computer Mathematics As discussed in the Preface, the main goal of the GuideBooks is to demonstrate, showcase, teach, and exemplify scientific problem solving with Mathematica. An important step in achieving this goal is the discussion of Mathematica functions that allow readers to become fluent in programming when creating complicated graphics or solving scientific problems. This again means that the reader must become familiar with the most important programming, graphics, numerics, and symbolics functions, their arguments, options, attributes, and a few of their time and space complexities. And the reader must know which functions to use in each situation. The GuideBooks treat only aspects of Mathematica that are ultimately related to “doing mathematics”. This means that the GuideBooks focus on the functionalities of the kernel rather than on those of the front end. The knowledge required to use the front end to work with the notebooks can easily be gained by reading the corresponding chapters of the online documentation of Mathematica. Some of the subjects that are treated either lightly or not at all in the GuideBooks include the basic use of Mathematica (starting the program, features, and special properties of the notebook front end [16]), typesetting, the preparation of packages, external file operations, the communication of Mathematica with other programs via MathLink, special formatting and string manipulations, computer- and operating system-specific operations, audio generation, and commands available in various packages. “Packages” includes both, those distributed with Mathematica as well as those available from the Mathematica Information Center (http://library.wolfram.com/infocenter) and commercial sources, such as MathTensor for doing general relativity calculations (http://smc.vnet.net/MathTensor.html) or FeynCalc for doing high-energy physics calculations (http://www.feyncalc.org). This means, in particular, that probability and statistical calculations are barely touched on because most of the relevant commands are contained in the packages. The GuideBooks make little or no mention of the machine-dependent possibilities offered by the various Mathematica implementations. For this information, see the Mathematica documentation.
xxii
Introduction
Mathematical and physical remarks introduce certain subjects and formulas to make the associated Mathematica implementations easier to understand. These remarks are not meant to provide a deep understanding of the (sometimes complicated) physical model or underlying mathematics; some of these remarks intentionally oversimplify matters. The reader should examine all Mathematica inputs and outputs carefully. Sometimes, the inputs and outputs illustrate little-known or seldom-used aspects of Mathematica commands. Moreover, for the efficient use of Mathematica, it is very important to understand the possibilities and limits of the built-in commands. Many commands in Mathematica allow different numbers of arguments. When a given command is called with fewer than the maximum number of arguments, an internal (or user-defined) default value is used for the missing arguments. For most of the commands, the maximum number of arguments and default values are discussed. When solving problems, the GuideBooks generically use a “straightforward” approach. This means they are not using particularly clever tricks to solve problems, but rather direct, possibly computationally more expensive, approaches. (From time to time, the GuideBooks even make use of a “brute force” approach.) The motivation is that when solving new “real life” problems a reader encounters in daily work, the “right mathematical trick” is seldom at hand. Nevertheless, the reader can more often than not rely on Mathematica being powerful enough to often succeed in using a straightforward approach. But attention is paid to Mathematica-specific issues to find time- and memory-efficient implementations—something that should be taken into account for any larger program. As already mentioned, all larger pieces of code in this book have comments explaining the individual steps carried out in the calculations. Many smaller pieces of code have comments when needed to expedite the understanding of how they work. This enables the reader to easily change and adapt the code pieces. Sometimes, when the translation from traditional mathematics into Mathematica is trivial, or when the author wants to emphasize certain aspects of the code, we let the code “speak for itself”. While paying attention to efficiency, the GuideBooks only occasionally go into the computational complexity ([8], [40], and [7]) of the given implementations. The implementation of very large, complicated suites of algorithms is not the purpose of the GuideBooks. The Mathematica packages included with Mathematica and the ones at MathSource (http://library.wolfram.com/ database/MathSource) offer a rich variety of self-study material on building large programs. Most general guidelines for writing code for scientific calculations (like descriptive variable names and modularity of code; see, e.g., [19] for a review) apply also to Mathematica programs. The programs given in a chapter typically make use of Mathematica functions discussed in earlier chapters. Using commands from later chapters would sometimes allow for more efficient techniques. Also, these programs emphasize the use of commands from the current chapter. So, for example, instead of list operation, from a complexity point of view, hashing techniques or tailored data structures might be preferable. All subsections and sections are “self-contained” (meaning that no other code than the one presented is needed to evaluate the subsections and sections). The price for this “self-containedness” is that from time to time some code has to be repeated (such as manipulating polygons or forming random permutations of lists) instead of delegating such programming constructs to a package. Because this repetition could be construed as boring, the author typically uses a slightly different implementation to achieve the same goal.
Introduction
xxiii
0.3.2 Programming Paradigms In the GuideBooks, the author wants to show the reader that Mathematica supports various programming paradigms and also show that, depending on the problem under consideration and the goal (e.g., solution of a problem, test of an algorithm, development of a program), each style has its advantages and disadvantages. (For a general discussion concerning programming styles, see [3], [41], [23], [32], [15], and [9].) Mathematica supports a functional programming style. Thus, in addition to classical procedural programs (which are often less efficient and less elegant), programs using the functional style are also presented. In the first volume of the Mathematica GuideBooks, the programming style is usually dictated by the types of commands that have been discussed up to that point. A certain portion of the programs involve recursive, rule-based programming. The choice of programming style is, of course, partially (ultimately) a matter of personal preference. The GuideBooks’ main aim is to explain the operation, limits, and efficient application of the various Mathematica commands. For certain commands, this dictates a certain style of programming. However, the various programming styles, with their advantages and disadvantages, are not the main concern of the GuideBooks. In working with Mathematica, the reader is likely to use different programming styles depending if one wants a quick one-time calculation or a routine that will be used repeatedly. So, for a given implementation, the program structure may not always be the most elegant, fastest, or “prettiest”. The GuideBooks are not a substitute for the study of The Mathematica Book [45] http://documents. wolfram.com/mathematica). It is impossible to acquire a deeper (full) understanding of Mathematica without a thorough study of this book (reading it twice from the first to the last page is highly recommended). It defines the language and the spirit of Mathematica. The reader will probably from time to time need to refer to parts of it, because not all commands are discussed in the GuideBooks. However, the story of what can be done with Mathematica does not end with the examples shown in The Mathematica Book. The Mathematica GuideBooks go beyond The Mathematica Book. They present larger programs for solving various problems and creating complicated graphics. In addition, the GuideBooks discuss a number of commands that are not or are only fleetingly mentioned in the manual (e.g., some specialized methods of mathematical functions and functions from the Developer` and Experimental` contexts), but which the author deems important. In the notebooks, the author gives special emphasis to discussions, remarks, and applications relating to several commands that are typical for Mathematica but not for most other programming languages, e.g., Map, MapAt, MapIndexed, Distribute, Apply, Replace, ReplaceAll, Inner, Outer, Fold, Nest, Nest List, FixedPoint, FixedPointList, and Function. These commands allow to write exceptionally elegant, fast, and powerful programs. All of these commands are discussed in The Mathematica Book and others that deal with programming in Mathematica (e.g., [33], [34], and [42]). However, the author’s experience suggests that a deeper understanding of these commands and their optimal applications comes only after working with Mathematica in the solution of more complicated problems. Both the printed book and the electronic component contain material that is meant to teach in detail how to use Mathematica to solve problems, rather than to present the underlying details of the various scientific examples. It cannot be overemphasized that to master the use of Mathematica, its programming paradigms and individual functions, the reader must experiment; this is especially important, insightful, easily verifiable, and satisfying with graphics, which involve manipulating expressions, making small changes, and finding different approaches. Because the results can easily be visually checked, generating and modifying graphics is an ideal method to learn programming in Mathematica.
xxiv
Introduction
0.4 Exercises and Solutions 0.4.1 Exercises Each chapter includes a set of exercises and a detailed solution proposal for each exercise. When possible, all of the purely Mathematica-programming related exercises (these are most of the exercises of the Programming volume) should be solved by every reader. The exercises coming from mathematics, physics, and engineering should be solved according to the reader’s interest. The most important Mathematica functions needed to solve a given problem are generally those of the associated chapter. For a rough orientation about the content of an exercise, the subject is included in its title. The relative degree of difficulty is indicated by level superscript of the exercise number ( L1 indicates easy, L2 indicates medium, and L3 indicates difficult). The author’s aim was to present understandable interesting examples that illustrate the Mathematica material discussed in the corresponding chapter. Some exercises were inspired by recent research problems; the references given allow the interested reader to dig deeper into the subject. The exercises are intentionally not hyperlinked to the corresponding solution. The independent solving of the exercises is an important part of learning Mathematica.
0.4.2 Solutions The GuideBooks contain solutions to each of the more than 1,000 exercises. Many of the techniques used in the solutions are not just one-line calls to built-in functions. It might well be that with further enhancements, a future version of Mathematica might be able to solve the problem more directly. (But due to different forms of some results returned by Mathematica, some problems might also become more challenging.) The author encourages the reader to try to find shorter, more clever, faster (in terms of runtime as well complexity), more general, and more elegant solutions. Doing various calculations is the most effective way to learn Mathematica. A proper Mathematica implementation of a function that solves a given problem often contains many different elements. The function(s) should have sensibly named and sensibly behaving options; for various (machine numeric, high-precision numeric, symbolic) inputs different steps might be required; shielding against inappropriate input might be needed; different parameter values might require different solution strategies and algorithms, helpful error and warning messages should be available. The returned data structure should be intuitive and easy to reuse; to achieve a good computational complexity, nontrivial data structures might be needed, etc. Most of the solutions do not deal with all of these issues, but only with selected ones and thereby leave plenty of room for more detailed treatments; as far as limit, boundary, and degenerate cases are concerned, they represent an outline of how to tackle the problem. Although the solutions do their job in general, they often allow considerable refinement and extension by the reader. The reader should consider the given solution to a given exercise as a proposal; quite different approaches are often possible and sometimes even more efficient. The routines presented in the solutions are not the most general possible, because to make them foolproof for every possible input (sensible and nonsensical, evaluated and unevaluated, numerical and symbolical), the books would have had to go considerably beyond the mathematical and physical framework of the GuideBooks. In addition, few warnings are implemented for improper or improperly used arguments. The graphics provided in the solutions are mostly subject to a long list of refinements. Although the solutions do work, they are often sketchy and can be considerably refined and extended by the reader. This also means that the provided solutions to the exercises programs are not always very suitable for
Introduction
xxv
solving larger classes of problems. To increase their applicability would require considerably more code. Thus, it is not guaranteed that given routines will work correctly on related problems. To guarantee this generality and scalability, one would have to protect the variables better, implement formulas for more general or specialized cases, write functions to accept different numbers of variables, add type-checking and error-checking functions, and include corresponding error messages and warnings. To simplify working through the solutions, the various steps of the solution are commented and are not always packed in a Module or Block. In general, only functions that are used later are packed. For longer calculations, such as those in some of the exercises, this was not feasible and intended. The arguments of the functions are not always checked for their appropriateness as is desirable for robust code. But, this makes it easier for the user to test and modify the code.
0.5 The Books Versus the Electronic Components 0.5.1 Working with the Notebooks Each volume of the GuideBooks comes with a multiplatform DVD, containing fourteen main notebooks tailored for Mathematica 4 and compatible with Mathematica 5. Each notebook corresponds to a chapter from the printed books. (To avoid large file sizes of the notebooks, all animations are located in the Animations directory and not directly in the chapter notebooks.) The chapters (and so the corresponding notebooks) contain a detailed description and explanation of the Mathematica commands needed and used in applications of Mathematica to the sciences. Discussions on Mathematica functions are supplemented by a variety of mathematics, physics, and graphics examples. The notebooks also contain complete solutions to all exercises. Forming an electronic book, the notebooks also contain all text, as well as fully typeset formulas, and reader-editable and reader-changeable input. (Readers can copy, paste, and use the inputs in their notebooks.) In addition to the chapter notebooks, the DVD also includes a navigation palette and fully hyperlinked table of contents and index notebooks. The Mathematica notebooks corresponding to the printed book are fully evaluated. The evaluated chapter notebooks also come with hyperlinked overviews; these overviews are not in the printed book. When reading the printed books, it might seem that some parts are longer than needed. The reader should keep in mind that the primary tool for working with the Mathematica kernel are Mathematica notebooks and that on a computer screen and there “length does not matter much”. The GuideBooks are basically a printout of the notebooks, which makes going back and forth between the printed books and the notebooks very easy. The GuideBooks give large examples to encourage the reader to investigate various Mathematica functions and to become familiar with Mathematica as a system for doing mathematics, as well as a programming language. Investigating Mathematica in the accompanying notebooks is the best way to learn its details. To start viewing the notebooks, open the table of contents notebook TableOfContents.nb. Mathematica notebooks can contain hyperlinks, and all entries of the table of contents are hyperlinked. Navigating through one of the chapters is convenient when done using the navigator palette GuideBooksNavigator.nb. When opening a notebook, the front end minimizes the amount of memory needed to display the notebook by loading it incrementally. Depending on the reader’s hardware, this might result in a slow scrolling speed. Clicking the “Load notebook cache” button of the GuideBooksNavigator palette speeds this up by loading the complete notebook into the front end. For the vast majority of sections, subsections, and solutions of the exercises, the reader can just select such a structural unit and evaluate it (at once) on a year-2005 computer (¥512 MB RAM) typically in a matter of
xxvi
Introduction
minutes. Some sections and solutions containing many graphics may need hours of computation time. Also, more than 50 pieces of code run hours, even days. The inputs that are very memory intensive or produce large outputs and graphics are in inactive cells which can be activated by clicking the adjacent button. Because of potentially overlapping variable names between various sections and subsections, the author advises the reader not to evaluate an entire chapter at once. Each smallest self-contained structural unit (a subsection, a section without subsections, or an exercise) should be evaluated within one Mathematica session starting with a freshly started kernel. At the end of each unit is an input cell. After evaluating all input cells of a unit in consecutive order, the input of this cell generates a short summary about the entire Mathematica session. It lists the number of evaluated inputs, the kernel CPU time, the wall clock time, and the maximal memory used to evaluate the inputs (excluding the resources needed to evaluate the Program cells). These numbers serve as a guide for the reader about the to-be-expected running times and memory needs. These numbers can deviate from run to run. The wall clock time can be substantially larger than the CPU time due to other processes running on the same computer and due to time needed to render graphics. The data shown in the evaluated notebooks came from a 2.5 GHz Linux computer. The CPU times are generically proportional to the computer clock speed, but can deviate within a small factor from operating system to operating system. In rare, randomly occurring cases slower computers can achieve smaller CPU and wall clock times than faster computers, due to internal time-constrained simplification processes in various symbolic mathematics functions (such as Integrate, Sum, DSolve, …). The Overview Section of the chapters is set up for a front end and kernel running on the same computer and having access to the same file system. When using a remote kernel, the directory specification for the package Overview.m must be changed accordingly. References can be conveniently extracted from the main text by selecting the cell(s) that refer to them (or parts of a cell) and then clicking the “Extract References” button. A new notebook with the extracted references will then appear. The notebooks contain color graphics. (To rerender the pictures with a greater color depth or at a larger size, choose Rerender Graphics from the Cell menu.) With some of the colors used, black-and-white printouts occasionally give low-contrast results. For better black-and-white printouts of these graphics, the author recommends setting the ColorOutput option of the relevant graphics function to GrayLevel. The notebooks with animations (in the printed book, animations are typically printed as an array of about 10 to 20 individual graphics) typically contain between 60 and 120 frames. Rerunning the corresponding code with a large number of frames will allow the reader to generate smoother and longer-running animations. Because many cell styles used in the notebooks are unique to the GuideBooks, when copying expressions and cells from the GuideBooks notebooks to other notebooks, one should first attach the style sheet notebook GuideBooksStylesheet.nb to the destination notebook, or define the needed styles in the style sheet of the destination notebook.
0.5.2 Reproducibility of the Results The 14 chapter notebooks contained in the electronic version of the GuideBooks were run mostly with Mathematica 5.1 on a 2 GHz Intel Linux computer with 2 GB RAM. They need more than 100 hours of evaluation time. (This does not include the evaluation of the currently unevaluatable parts of code after the Make Input buttons.) For most subsections and sections, 512 MB RAM are recommended for a fast and smooth evaluation “at once” (meaning the reader can select the section or subsection, and evaluate all inputs without running out of memory or clearing variables) and the rendering of the generated graphic in the front end. Some subsections and sections
Introduction
xxvii
need more memory when run. To reduce these memory requirements, the author recommends restarting the Mathematica kernel inside these subsections and sections, evaluating the necessary definitions, and then continuing. This will allow the reader to evaluate all inputs. In general, regardless of the computer, with the same version of Mathematica, the reader should get the same results as shown in the notebooks. (The author has tested the code on Sun and Intel-based Linux computers, but this does not mean that some code might not run as displayed (because of different configurations, stack size settings, etc., but the disclaimer from the Preface applies everywhere). If an input does not work on a particular machine, please inform the author. Some deviations from the results given may appear because of the following: † Inputs involving the function Random[…] in some form. (Often SeedRandom to allow for some kind of reproducibility and randomness at the same time is employed.) † Mathematica commands operating on the file system of the computer, or make use of the type of computer (such inputs need to be edited using the appropriate directory specifications). † Calculations showing some of the differences of floating-point numbers and the machine-dependent representation of these on various computers. † Pictures using various fonts and sizes because of their availability (or lack thereof) and shape on different computers. † Calculations involving Timing because of different clock speeds, architectures, operating systems, and libraries. † Formats of results depending on the actual window width and default font size. (Often, the corresponding inputs will contain Short.) Using anything other than Mathematica Version 5.1 might also result in different outputs. Examples of results that change form, but are all mathematically correct and equivalent, are the parameter variables used in underdetermined systems of linear equations, the form of the results of an integral, and the internal form of functions like InterpolatingFunction and CompiledFunction. Some inputs might no longer evaluate the same way because functions from a package were used and these functions are potentially built-in functions in a later Mathematica version. Mathematica is a very large and complicated program that is constantly updated and improved. Some of these changes might be design changes, superseded functionality, or potentially regressions, and as a result, some of the inputs might not work at all or give unexpected results in future versions of Mathematica.
0.5.3 Earlier Versions of the Notebooks The first printing of the Programming volume and the Graphics volumes of the Mathematica GuideBooks were published in October 2004. The electronic components of these two books contained the corresponding evaluated chapter notebooks as well as unevaluated versions of preversions of the notebooks belonging to the Numerics and Symbolics volumes. Similarly, the electronic components of the Numerics and Symbolics volume contain the corresponding evaluated chapter notebooks and unevaluated copies of the notebooks of the Programming and Graphics volumes. This allows the reader to follow cross-references and look up relevant concepts discussed in the other volumes. The author has tried to keep the notebooks of the GuideBooks as up-to-date as possible. (Meaning with respect to the efficient and appropriate use of the latest version of Mathematica, with respect to maintaining a list of references that contains new publications, and examples, and with respect to incorporating corrections to known problems, errors, and mistakes). As a result, the notebooks of all four volumes that come with later printings of the Programming and Graphics volumes, as well with the Numerics and Symbolics volumes will be different and supersede the earlier notebooks originally distributed with the
Introduction
xxviii
Programming and Graphics volumes. The notebooks that come with the Numerics and Symbolics volumes are genuine Mathematica Version 5.1 notebooks. Because most advances in Mathematica Version 5 and 5.1 compared with Mathematica Version 4 occurred in functions carrying out numerical and symbolical calculations, the notebooks associated with Numerics and Symbolics volumes contain a substantial amount of changes and additions compared with their originally distributed version.
0.6 Style and Design Elements 0.6.1 Text and Code Formatting The GuideBooks are divided into chapters. Each chapter consists of several sections, which frequently are further subdivided into subsections. General remarks about a chapter or a section are presented in the sections and subsections numbered 0. (These remarks usually discuss the structure of the following section and give teasers about the usefulness of the functions to be discussed.) Also, sometimes these sections serve to refresh the discussion of some functions already introduced earlier. Following the style of The Mathematica Book [45], the GuideBooks use the following fonts: For the main text, Times; for Mathematica inputs and built-in Mathematica commands, Courier plain (like Plot); and for user-supplied arguments, Times italic (like userArgument1 ). Built-in Mathematica functions are introduced in the following style: MathematicaFunctionToBeIntroduced[typeIndicatingUserSuppliedArgument(s)] is a description of the built-in command MathematicaFunctionToBeIntroduced upon its first appearance. A definition of the command, along with its parameters is given. Here, typeIndicatingUserSuppliedArgument(s) is one (or more) user-supplied expression(s) and may be written in an abbreviated form or in a different way for emphasis.
The actual Mathematica inputs and outputs appear in the following manner (as mentioned above, virtually all inputs are given in InputForm). (* A comment. It will be/is ignored as Mathematica input: Return only one of the solutions *) Last[Solve[{x^2 - y == 1, x - y^2 == 1}, {x, y}]]
When referring in text to variables of Mathematica inputs and outputs, the following convention is used: Fixed, nonpattern variables (including local variables) are printed in Courier plain (the equations solved above contained the variables x and y). User supplied arguments to built-in or defined functions with pattern variables are printed in Times italic. The next input defines a function generating a pair of polynomial equations in x and y. equationPair[x_, y_] := {x^2 - y == 1, x - y^2 == 1}
x and y are pattern variables (usimng the same letters, but a different font from the actual code fragments x_ and y_) that can stand for any argument. Here we call the function equationPair with the two arguments u + v and w - z. equationPair[u + v, w - z]
Occasionally, explanation about a mathematics or physics topic is given before the corresponding Mathematica implementation is discussed. These sections are marked as follows:
Introduction
xxix
Mathematical Remark: Special Topic in Mathematics or Physics A short summary or review of mathematical or physical ideas necessary for the following example(s). 1
From time to time, Mathematica is used to analyze expressions, algorithms, etc. In some cases, results in the form of English sentences are produced programmatically. To differentiate such automatically generated text from the main text, in most instances such text is prefaced by “ë” (structurally the corresponding cells are of type "PrintText" versus "Text" for author-written cells). Code pieces that either run for quite long, or need a lot of memory, or are tangent to the current discussion are displayed in the following manner. Make Input
mathematicaCodeWhichEitherRunsVeryLongOrThatIsVeryMemoryIntensive OrThatProducesAVeryLargeGraphicOrThatIsASideTrackToTheSubjectUnder Discussion (* with some comments on how the code works *)
To run a code piece like this, click the Make Input button above it. This will generate the corresponding input cell that can be evaluated if the reader’s computer has the necessary resources. The reader is encouraged to add new inputs and annotations to the electronic notebooks. There are two styles for reader-added material: "ReaderInput" (a Mathematica input style and simultaneously the default style for a new cell) and "ReaderAnnotation" (a text-style cell type). They are primarily intended to be used in the Reading environment. These two styles are indented more than the default input and text cells, have a green left bar and a dingbat. To access the "ReaderInput" and "ReaderAnnotation" styles, press the system-dependent modifier key (such as Control or Command) and 9 and 7, respectively.
0.6.2 References Because the GuideBooks are concerned with the solution of mathematical and physical problems using Mathematica and are not mathematics or physics monographs, the author did not attempt to give complete references for each of the applications discussed [38], [20]. The references cited in the text pertain mainly to the applications under discussion. Most of the citations are from the more recent literature; references to older publications can be found in the cited ones. Frequently URLs for downloading relevant or interesting information are given. (The URL addresses worked at the time of printing and, hopefully, will be still active when the reader tries them.) References for Mathematica, for algorithms used in computer algebra, and for applications of computer algebra are collected in the Appendix A. The references are listed at the end of each chapter in alphabetical order. In the notebooks, the references are hyperlinked to all their occurrences in the main text. Multiple references for a subject are not cited in numerical order, but rather in the order of their importance, relevance, and suggested reading order for the implementation given. In a few cases (e.g., pure functions in Chapter 3, some matrix operations in Chapter 6), references to the mathematical background for some built-in commands are given—mainly for commands in which the mathematics required extends beyond the familiarity commonly exhibited by non-mathematicians. The GuideBooks do not discuss the algorithms underlying such complicated functions, but sometimes use Mathematica to “monitor” the algorithms.
xxx
Introduction
References of the form abbreviationOfAScientificField/yearMonthPreprintNumber (such as quant-ph/0012147) refer to the arXiv preprint server [43], [22], [30] at http://arXiv.org. When a paper appeared as a preprint and (later) in a journal, typically only the more accessible preprint reference is given. For the convenience of the reader, at the end of these references, there is a Get Preprint button. Click the button to display a palette notebook with hyperlinks to the corresponding preprint at the main preprint server and its mirror sites. (Some of the older journal articles can be downloaded free of charge from some of the digital mathematics library servers, such as http://gdz.sub.uni-goettingen.de, http://www.emis.de, http://www.numdam.org, and http://dieper.aib.unilinz.ac.at.) As much as available, recent journal articles are hyperlinked through their digital object identifiers (http://www.doi.org).
0.6.3 Variable Scoping, Input Numbering, and Warning Messages Some of the Mathematica inputs intentionally cause error messages, infinite loops, and so on, to illustrate the operation of a Mathematica command. These messages also arise in the user’s practical use of Mathematica. So, instead of presenting polished and perfected code, the author prefers to illustrate the potential problems and limitations associated with the use of Mathematica applied to “real life” problems. The one exception are the spelling warning messages General::spell and General::spell1 that would appear relatively frequently because “similar” names are used eventually. For easier and less defocused reading, these messages are turned off in the initialization cells. (When working with the notebooks, this means that the pop-up window asking the user “Do you want to automatically evaluate all the initialization cells in the notebook?” should be evaluated should always be answered with a “yes”.) For the vast majority of graphics presented, the picture is the focus, not the returned Mathematica expression representing the picture. That is why the Graphics and Graphics3D output is suppressed in most situations. To improve the code’s readability, no attempt has been made to protect all variables that are used in the various examples. This protection could be done with Clear, Remove, Block, Module, With, and others. Not protecting the variables allows the reader to modify, in a somewhat easier manner, the values and definitions of variables, and to see the effects of these changes. On the other hand, there may be some interference between variable names and values used in the notebooks and those that might be introduced when experimenting with the code. When readers examine some of the code on a computer, reevaluate sections, and sometimes perform subsidiary calculations, they may introduce variables that might interfere with ones from the GuideBooks. To partially avoid this problem, and for the reader’s convenience, sometimes Clear[sequenceOfVariables]and Remove[sequenceOfVariables] are sprinkled throughout the notebooks. This makes experimenting with these functions easier. The numbering of the Mathematica inputs and outputs typically does not contain all consecutive integers. Some pieces of Mathematica code consist of multiple inputs per cell; so, therefore, the line numbering is incremented by more than just 1. As mentioned, Mathematica should be restarted at every section, or subsection or solution of an exercise, to make sure that no variables with values get reused. The author also explicitly asks the reader to restart Mathematica at some special positions inside sections. This removes previously introduced variables, eliminates all existing contexts, and returns Mathematica to the typical initial configuration to ensure reproduction of the results and to avoid using too much memory inside one session.
Introduction
xxxi
0.6.4 Graphics In Mathematica 5.1, displayed graphics are side effects, not outputs. The actual output of an input producing a graphic is a single cell with the text Graphics or Graphics3D or GraphicsArray and so on. To save paper, these output cells have been deleted in the printed version of the GuideBooks. Most graphics use an appropriate number of plot points and polygons to show the relevant features and details. Changing the number of plot points and polygons to a higher value to obtain higher resolution graphics can be done by changing the corresponding inputs. The graphics of the printed book and the graphics in the notebooks are largely identical. Some printed book graphics use a different color scheme and different point sizes and line and edge thicknesses to enhance contrast and visibility. In addition, the font size has been reduced for the printed book in tick and axes labels. The graphics shown in the notebooks are PostScript graphics. This means they can be resized and rerendered without loss of quality. To reduce file sizes, the reader can convert them to bitmap graphics using the Cellö Convert ToöBitmap menu. The resulting bitmap graphics can no longer be resized or rerendered in the original resolution. To reduce file sizes of the main content notebooks, the animations of the GuideBooks are not part of the chapter notebooks. They are contained in a separate directory.
0.6.5 Notations and Symbols The symbols used in typeset mathematical formulas are not uniform and unique throughout the GuideBooks. Various mathematical and physical quantities (such as normals, rotation matrices, and field strengths) are used repeatedly in this book. Frequently the same notation is used for them, but depending on the context, also different ones are used, e.g. sometimes bold is used for a vector (such as r) and sometimes an arrow (such as ”r). Matrices appear in bold or as doublestruck letters. Depending on the context and emphasis placed, different notations are used in display equations and in the Mathematica input form. For instance, for a time-dependent scalar quantity of one variable yHt; xL, we might use one of many patterns, such as ψ[t][x] (for emphasizing a parametric t-dependence) or ψ[t, x] (to treat t and x on an equal footing) or ψ[t, {x}] (to emphasize the one-dimensionality of the space variable x). Mathematical formulas use standard notation. To avoid confusion with Mathematica notations, the use of square brackets is minimized throughout. Following the conventions of mathematics notation, square brackets are used for three cases: a) Functionals, such as t @ f HtLD HwL for the Fourier transform of a function f HtL. b) Power series coefficients, @xk D H f HxLL denotes the coefficient of xk of the power series expansion of f HxL around x = 0. c) Closed intervals, like @a, bD (open intervals are denoted by Ha, bL). Grouping is exclusively done using parentheses. Upper-case double-struck letters denote domains of numbers, for integers, for nonnegative integers, for rational numbers, for reals, and for complex numbers. Points in n (or n ) with explicitly given coordinates are indicated using curly braces 8c1 , …, cn w;
Numerical Computations
6 In[39]:=
(* a basis for the ideal generated by odeJ, D[odeJ, z], and D[odeJ, z, z] *) gb = GroebnerBasis[{odeJ, D[odeJ, z], D[odeJ, z, z]}, (* derivatives are the variables *) Table[Derivative[k][w][z], {k, 0, 5}], MonomialOrder -> DegreeReverseLexicographic];
In[41]:=
(* odeNum lies in the above ideal *) PolynomialReduce[odeNum, gb, Table[Derivative[k][w][z], {k, 0, 5}], MonomialOrder -> DegreeReverseLexicographic][[2]] 0
Out[42]=
The 0 in the second element of the last list returned by PolynomialReduce shows that odeNum follows from odeJ. We give another introductory example for the use of high-precision arithmetic. Here is a trajectory (starting at the origin) of the famous Rössler system, x£ HtL = - yHtL - zHtL y£ HtL = xHtL + a yHtL z£ HtL = b - c zHtL + xHtL zHtL a coupled system of three nonlinear ordinary differential equations. (We use the parameter values a = 1 ê 2, b = 2, and c = 4.) In[43]:=
Module[{a = 1/2, b = 2, c = 4, T = 500}, ndsolRössler = NDSolve[{x'[t] == -y[t] - z[t], y'[t] == x[t] + a y[t], z'[t] == b + x[t] z[t] - c z[t], (* start at the origin *) x[0] == 0, y[0] == 0, z[0] == 0}, {x, y, z}, {t, 0, T}, MaxSteps -> 10^5]; (* show trajectory *) ParametricPlot3D[Evaluate[{x[t], y[t], z[t]} /. ndsolRössler[[1]]], {t, 0, T}, PlotPoints -> 10000, PlotRange -> All]];
-6
-4
-2
0
2 -2.5
0
2.5
5
10 7.5 5 2.5 0
While the built-in function NDSolve can easily solve these differential equations, we will quickly investigate the value of the largest step size h that can be used in a simple forward Euler discretization so that the trajectories do not escape to infinity [1131]: HhL HhL xHhL n+1 = xn + h H- yn - zn L
HhL HhL yHhL n+1 = yn + h Hxn + a yn L
HhL HhL HhL zHhL n+1 = zn + h Hb - c zn + xn zn L
1.0 Remarks In[44]:=
7
hpEuler[n_, h_, xyz0_:{0, 0, 0}] := Module[{a = 1/2, b = 2, c = 4, x = xyz0[[1]], y = xyz0[[2]], z = xyz0[[3]]}, Table[{x, y, z} = {x + h (-y - z), y + h (x + a y), z + h (b + x z - c z)}, {n}]]
The next series of five graphics shows the solution obtained from using the Euler discretization for step sizes k 10-2 for k = 1, …, 6. We follow the solution over a time interval of length 100. We use a step size of precision 1000. This guarantees that we have at t = 100 still about 800 valid digits left. In[45]:=
Show[GraphicsArray[ Table[Graphics3D[Line[N[hpEuler[Round[10^4/k], N[k 10^-2, 10^3]]]], PlotRange -> All, PlotLabel -> k], {k, 6}]]] 1
2
3
4
5
6
Starting with an upper bound for the maximal step size (meaning a step size so that the trajectory surely diverges—we use the value 1 here), it is straightforward to implement a simple bisection algorithm findMaxi malStepSize that brackets the maximal step size in an interval of length ¶. To get a sufficiently small interval HhL HhL for the step size, we use high-precision arithmetic with initial 4000 digits to evolve the 8xHhL n , yn , zn escape, hMax = hNew, hMin = hNew]; print[{k, N[hMax - hMin]}], {k, Ceiling[Log[1/2, ∂]] + 1}]; (* turn on message *) If[Head[msg] === String, On[General::ovfl]]; {hMin, hMax}]
For a given bracketing interval HhMin, hMaxL for the maximal step size, the function makeTrajectory Graphics visualizes various properties of the corresponding forward iterated solutions. The first row of graphics shows the trajectories for step sizes hMin ê 10 (surely nondiverging), hMin (on the edge of diverging), HhL HhL and hMax (barely diverging). The second row shows the precision of the 8xHhL n , yn , zn < as a function of n HhL HhL (making sure that in all iteration steps we still have digits left), the components xn , yHhL n , and zn as a function of Hhmax L Hhmin L Hhmax L Hhmin L Hhmax L Hhmin L xn §, †yn - yn §, †zn - zn §< as a function of n. n and the last graphic shows 8†xn In[49]:=
makeTrajectoryGraphics[hp_, {hMin_, hMax_}, o_, prec_:4000] := Module[{cOpts, dataMinP, dataMin, dataMaxP, dataMax, dataSmall, max, pos, pr},
Numerical Computations
8
cOpts[x_] := Sequence[PlotRange -> All, BoxRatios -> {1, 1, 1}, Axes -> True, PlotRange -> All, PlotLabel -> Subscript["h", x]]; (* iterate forward propagation *) {dataMinP, dataMaxP, dataSmall} = hp[o, N[Rationalize[#, 0], prec]]& /@ {hMin, hMax, (hMin + hMax)/10}; (* extract nondiverging part of diverging trajectory *) max = 2 Max[Abs[dataMinP]]; pos = Position[dataMaxP, _?(Max[Abs[#]] > max&), {1}, 1][[1, 1]]; dataMax = Take[dataMaxP, pos]; dataMin = Take[dataMinP, pos]; (* make two graphics arrays *) GraphicsArray /@ Block[{$DisplayFunction = Identity, pr = FullOptions[Graphics3D[Line[dataMinP], PlotRange -> All], PlotRange], xTicks = Table[k 1000, {k, 0, Round[Log[10, o + 1]]}], rgb = {RGBColor[1, 0, 0], RGBColor[0, 1, 0], RGBColor[0, 0, 1]}}, Print[xTicks]; (* show trajectories for three step sizes *) {Graphics3D[Line[#1], PlotRange -> 3/2 pr, cOpts[#2]]& @@@ {{dataSmall, "small"}, {dataMinP, "min"}, {dataMax, "max"}}, (* precision of iterates *) {Graphics[{PointSize[0.003], Transpose[{rgb, MapIndexed[Point[{#2[[1]] - 1, Precision[#1]}]&, #]& /@ {dataSmall, dataMinP, dataMax}}]}, PlotRange -> {All, {0, 1.1 prec}}, Frame -> True, PlotLabel -> "Precision"], (* x, y, and z-component of iterates *) Graphics[{PointSize[0.003], Transpose[{rgb, MapIndexed[Point[{#2[[1]] - 1, #1}]&, #]& /@ Transpose[dataMax]}]}, Frame -> True, PlotRange -> {{0, o}, Automatic}, FrameTicks -> {xTicks, Automatic, None, None}, PlotLabel -> (Subscript[#, n]& /@ {x, y, z})], (* difference in trajectories does bracketing step sizes *) Graphics[{PointSize[0.003], Transpose[{rgb, MapIndexed[If[# != 0, Point[{#2[[1]] - 1, Log[10, Abs[#1]]}], {}]&, #]& /@ Transpose[N[dataMax - Take[dataMin, pos]]]}]}, Frame -> True, PlotRange -> {{0, o}, Automatic}, FrameTicks -> {xTicks, Automatic, None, None}, PlotLabel -> (Subscript[#, n]& /@ {δx, δy, δz})]}}]]
Here are the just-described graphics for the Euler iterations for a starting interval of length 10-25 . We obtain General::ovfl messages from the diverging trajectories. The maximal step length is hmax = 0.06832597…. In[50]:= Out[50]= In[51]:=
findMaximalStepSize[hpEuler, 10^-25] 1321616582571470688732441 2643233165142941377464883 9 , = 19342813113834066795298816 38685626227668133590597632 Show /@ makeTrajectoryGraphics[hpEuler, (* findMaximalStepSize[hpEuler, 10^-25] = *) {1321616582571470688732441/19342813113834066795298816, 2643233165142941377464883/38685626227668133590597632}, 4000] General::ovfl : Overflow occurred in computation. More…
1.0 Remarks
9 80, 1000, 2000, 3000, 4000< 0
hsmall
hmin
0
-5
0
-10
-10
-10
30
30
30
20
20
20
10
10
0
10
0
-5
0
-5
0
-5
0
5
0
5 10
5 10
10
8xn , yn , z n
False, PlotRange -> All, Axes -> False]}]]]
So far, we have discussed the usefulness of high-precision arithmetic for numerical calculations. High-precision arithmetic allows one to obtain reliable results with many digits that sometimes are impossible to obtain using machine arithmetic. On the other hand, for many calculations, machine precision is sufficient and speed is
1.0 Remarks
11
essential. Mathematica frequently compiles numerical calculations invisible to the user to accelerate calculations and also allows for explicit compilation. Because of the importance of compilation, let us give one typical example in this introductory section. We will encounter many more invocations of the Compile function throughout this chapter. We consider a simple 1D molecular dynamics simulation [661], [1897], [1548], [1505], [766]. Between two walls, located at z = 0 and z = L we have n particles with potentially different masses. If two (or more) particles meet, and have a center of mass energy less than V, they undergo an elastic collision. If they have a center of mass energy greater than V , they just move through each other (this is a very crude model of a realistic collision process). The two walls are held at temperatures T0 and TL and if particles collide with the walls they thermalize, meaning, after the wall collision, their velocities are Maxwellian with temperature T0 or TL . In the following, we will assume the data for each particle in the form {particleNumber, mass, startTime, startPoint, velocity} and the data for all particles is a list of such 5-element lists. The function collisionStep evolves a system of particles until the next collision and returns the particle data with the new startTimes, startPoints, and velocities. We account for the possibility that more than one collision could happen at one time. In[55]:=
collisionStep[particleData_?(MatrixQ[#, NumberQ]&), L_, V_, Ts_?(VectorQ[#, NumberQ]&)] := Module[{, , n, tOld, cts, δxδvs, leftt, rightt, ts, tC, cList, c, m1, v1, m2, v2, Tc, V1, V2, , T0 = Ts[[1]], TL = Ts[[2]]}, = particleData; = ; = $MaxMachineNumber/10; n = Length[]; tOld = [[1, 3]]; (* collision of all adjacent pairs *) δxδvs = {#[[2, 4]] - #[[1, 4]], #[[1, 5]] - #[[2, 5]]}& /@ Partition[, 2, 1]; cts = If[#[[2]] == 0., , #[[1]]/#[[2]]]& /@ δxδvs; {leftt, rightt} = {0 - [[1, 4]]/[[1, 5]], (L - [[n, 4]])/[[n, 5]]}; ts = Join[{leftt}, cts, {rightt}]; (* time of next collision *) tC = Max[ts]; Do[If[0. < ts[[j]] < tC, tC = ts[[j]]], {j, Length[ts]}]; (* list of colliding pairs; multiple collision can (depending on time granularity) happen at the same time *) (* which particles collide? *) cList = {-1}; Do[If[ts[[j]] == tC, AppendTo[cList, j - 1]], {j, n + 1}]; (* new collision times and new positions *) Do[[[j, 3]] = tOld + tC; [[j, 4]] = [[j, 4]] + tC [[j, 5]], {j, n}]; (* carry out the collision(s) *) Do[c = cList[[j]]; Which[(* left wall collision *) c == 0, [[1, 4]] = 0.; (* thermalize on left wall *) [[1, 5]] = Sqrt[2 T0/[[1, 2]]] Abs[InverseErf[2 Random[] - 1]], (* two particle collision *) 0 < c < n, {m1, v1} = [[c, {2, 5}]]; {m2, v2} = [[c + 1, {2, 5}]]; If[(* high-energy collision *) Tc = 1/2 m1 m2/(m1 + m2) (v1 - v2)^2; Tc > V, {[[c]], [[c + 1]]} = {[[c + 1]], [[c]]}; [[c + 1, 4]] = [[c, 4]], (* else -- a real collision *) (* velocities after collision *) {V1, V2} = {v1, v2} + 2 {m2, -m1}(v2 - v1)/(m1 + m2); {[[c, 5]], [[c + 1, 5]]} = {V1, V2}; [[c + 1, 4]] = [[c, 4]]],
Numerical Computations
12
(* right wall collision *) c == n, [[n, 4]] = L; (* thermalize on right wall *) [[n, 5]] = -Sqrt[2 TL/[[n, 2]]] Abs[InverseErf[2 Random[] - 1]]], {j, 2, Length[cList]}]; (* do nearby in time collisions *) Do[If[[[j, 4]] == [[j + 1, 4]] && [[j, 5]] > [[j + 1, 5]], [[j + 1, 4]] = [[j, 4]]; {[[j]], [[j + 1]]} = {[[j + 1]], [[j]]}], {j, n - 1}]; If[[[1, 4]] == 0. && [[1, 5]] < 0., [[1, 5]] = -[[1, 5]]]; If[[[n, 4]] == L && [[n, 5]] > 0., [[n, 5]] = -[[n, 5]]]; (* return new state *) ]
To visualize the trajectories of the particles, we implement a function collisionHistoryGraphics that shows the space-time curves of the particles with time running upwards. We color the particles according to their mass. In[56]:=
collisionHistoryGraphics[collisions_, L_, opts___] := Module[{segments = Transpose /@ Partition[Sort /@ collisions, 2, 1]}, Graphics[{(* the two walls *) {GrayLevel[0.5], Thickness[0.02], Line[{{0, #1}, {0, #2}}], Line[{{L, #1}, {L, #2}}]}& @@ ({Min[#], Max[#]}&[#[[1, 3]]& /@ collisions]), (* the particle trajectories *) {Map[{Hue[#[[1, 2]]], Line[{{#[[1, 4]], #[[1, 3]]}, {#[[2, 4]], #[[2, 3]]}}]}&, segments, {2}]}}, opts, FrameTicks -> None, Frame -> True, PlotRange -> {{-L/10, 1.1 L}, All}, AspectRatio -> 1]]
Here is an example. We start with 30 particles with random masses, starting points, and starting velocities in a well of length 100. The leftmost graphic uses V = ¶, meaning all collisions are elastic. As a result, only after the first particle hits a wall (with temperature 10; the Boltzmann constant is set to 1), we see an interesting structure of the trajectories evolving, propagating from the right to the left through successive collisions. The middle and right graphics use V = 2 and V = 1. Because now some collisions do not happen, the disturbance can propagate more quickly to the left through a particle not colliding with each particle on the way. In[57]:=
Module[{n = 30, Ts = {10, 10}, L = 100, cs = 1000, pd, data, particleData}, SeedRandom[33]; (* initial particle positions and velocities *) particleData = Sort[Table[{k, 0.8 Random[], 0, L Random[], 1/100 (2 Random[Integer] - 1)}, {k, n}], (* sort left to right *) #1[[4]] < #2[[4]]&]; (* show the three graphics *) Show[GraphicsArray[ Function[V, (* initialize random number generation *) SeedRandom[111]; (* carry out cs collisions *) data = NestList[collisionStep[#, L, V, Ts]&, particleData, cs]; collisionHistoryGraphics[data, L]] /@ {Infinity, 2, 1}]]]
1.0 Remarks
13
Next, we will use two kinds of particles (meaning two masses) and walls of different temperatures. We expect to see the Ludwig–Soret effect [761] in the resulting spatial distribution of the particles, meaning the lighter particles should accumulate near the cold wall. We now carry out 1000 collisions for 2 μ 50 particles with masses m = 1 and m = 0.12, wall temperatures T0 = 0 and T200 = 10. particleData is the random initial configuration of the particles. In[58]:=
particleData = With[{n = 50, Ta = 5.5, L = 200, μ1 = 1., μ2 = 0.12}, Sort[Join[(* initial conditions for heavy particles *) Table[{k, μ1, 0., L Random[], Sqrt[2 Ta/μ1] InverseErf[2 Random[] - 1]}, {k, n}], (* initial conditions for light particles *) Table[{n + k, μ2, 0., L Random[], Sqrt[2 Ta/μ2] InverseErf[2 Random[] - 1]}, {k, n}]], (* sort left to right *) #1[[4]] < #2[[4]]&]];
We carry out 100 collisions using the initial configuration particleData and measure how long this takes. In[59]:=
Out[60]=
L = 200; n = 50; SeedRandom[111]; (dataLS1 = NestList[collisionStep[#, L, 2, {1, 10}]&, particleData, 100]); // Timing 80.45 Second, Null
Identity]& @@@ (* light particles in red; heavy particles in blue *) {{First, RGBColor[0, 0, 1]}, {Last, RGBColor[1, 0, 0]}} , DisplayFunction -> $DisplayFunction, AspectRatio -> 1/4, PlotRange -> All, Axes -> False, Frame -> True] 140 120 100 80 60 40 20 0
200
400
600
800
1000
Many related simulations could be carried out, such as modeling the gas temperature for finite reservoirs [1115].
1.1 Approximate Numbers
15
1.1 Approximate Numbers 1.1.0 Remarks This subsection will cover the basics of the usage and underlying principles of machine and high-precision numbers. While calculations with machine numbers have been used already extensively in the chapters of the Programming [1793] and Graphics [1794] volumes, high-precision arithmetic was used only rarely. So in the next subsection we will discuss the notations of precision and accuracy of a real and a complex number, the principles of automatic precision control and its consequences, the phenomena of precision gain and loss in calculations, and the possibilities to raise or lower the precision or accuracy of a number. Later we will investigate the internal structure of high-precision numbers and how high-precision numbers are treated special in functions like Union and which system options are of relevance here. In discussing all these subjects, we will provide a large number of examples to demonstrate all statements. The second subsection will deal with intervals. Intervals provide a method to carry out validated numerical calculations. The third subsection will discuss continued fractions and related expansions in detail. Continued fractions are relevant for converting approximate numbers to nearby rational numbers. The last subsection of this section deals with a more advanced topic for machine number calculations—packed arrays. While packed arrays are in many instances automatically generated by Mathematica without the users explicit influences, for more complicated calculations it is sometimes necessary for the user to pack and unpack lists of machine numbers under his guidance to achieve optimal performance.
1.1.1 Numbers with an Arbitrary Number of Digits For most numerical calculations, around 14 to 19 digits of (hardware-dependent) machine precision is adequate. Machine arithmetic is used when evaluating expressions of the form N[expr]. However, sometimes we would like to work with more digits to ensure that a certain number of interesting digits is correct. (For several examples, it is necessary to use more than around 20 digits in applications; see [1904], [1667], [1349], [453], [503], and [413].) In such situations, Mathematica’s high-precision numbers, together with their automatic precision control, come in very handy. We will use Mathematica’s high-precision capabilities many times in this and the following chapters. We have already introduced N[expression, digits] in Chapter 2 of the Programming volume [1793]. It computes the expression expression to a precision of digits digits. Mathematica’s high-precision arithmetic is based on significance arithmetic (see [1266] and [1267]). This means that the result of a high-precision calculation is a number (composed of digits) including the knowledge of which of the digits are correct. In OutputForm and StandardForm only the certified digits are printed. InputForm and FullForm will display all digits together with the information of how many of them are correct. In a nutshell, here is how Mathematica can be used to carry out high-precision arithmetic. In principle, there are three possibilities: † Floating-point arithmetic with a fixed number of digits. This can be forced by choosing $MinPrecision = $MaxPrecision = number (which is better used inside a Block by using localized versions of $MinPreci
Numerical Computations
16 sion and $MaxPrecision).
† Floating-point arithmetic with a variable number of digits. This is the method implemented in the current Mathematica kernel. Roughly speaking, the main idea is to simulate interval arithmetic by constantly maintaining a “few more digits” than needed (hereafter called guard digits), and to use them to analyze the error. † Interval arithmetic. This stricter method is implemented in Mathematica for real numbers (see the subsection below). For more detailed information on Mathematica’s implementation of bignum arithmetic and interval arithmetic (see below), as well as a discussion of the general problem of calculating with approximate numbers and intervals, see [967], [830], [964], [887], [697], [1667], [1293], [1294], [36], [959], [1850], [968], and [969]. In the last section, we used high-precision arithmetic to “check” an identity numerically. Because we obtained zero to hundreds of digits we did not have to worry about the correctness of the digits. (The probability that the identity would be wrong and that accumulated errors in the carried out arithmetic make a wrong identity correct is vanishing small.) In the next two introductory examples, we are not primarily dealing with many digits, but rather how much we can trust the digits calculated. Here is a first simple example using high-precision arithmetic. This is an iterated modified logistic map [735], [539]. In[1]:=
modifiedLogisticMap[x_, λ_, ∂_, n_] = (λ + (-1)^n ∂) x (1 - x); modifiedLogisticMapData[x0_, λ_, ∂_, l_, l0_] := Drop[FoldList[modifiedLogisticMap[#, λ, ∂, #2]&, x0, Range[l]], l0]
Making a plot using machine arithmetic yields a “typical” looking picture for a logistic equation [949]. In[3]:=
Show[Graphics[{PointSize[0.003], Table[Point[{λ, #}]& /@ modifiedLogisticMapData[1/210, λ, 0.2, 300, 100], {λ, 2.6, 3.8, 0.01}]}], PlotRange -> All, Frame -> True] 0.9 0.8 0.7 0.6 0.5 0.4 0.3
2.6
2.8
3
3.2
3.4
3.6
3.8
Using bignum arithmetic yields a qualitatively similar looking picture. In[4]:=
Show[Graphics[{PointSize[0.003], Table[Point[{λ, #}]& /@ modifiedLogisticMapData[N[1/210, 200], λ, 2/10, 300, 100], {λ, 26/10, 38/10, 1/100}]}], PlotRange -> All, Frame -> True]
1.1 Approximate Numbers
17
0.9 0.8 0.7 0.6 0.5 0.4 0.3
2.6
2.8
3
3.2
3.4
3.6
3.8
But the actual orbit for a fixed l shows that after around 50 iterations, the machine result is wrong. In[5]:=
ListPlot[ (* difference between machine-precision and high-precision version *) modifiedLogisticMapData[1/210, 3.49, 0.2, 300, 100] modifiedLogisticMapData[N[1/210, 200], 349/100, 2/10, 300, 100], PlotJoined -> True, PlotRange -> All, Frame -> True, Axes -> False] 0.4
0.2
0
-0.2
-0.4 0
50
100
150
200
As long as the calculated high-precision numbers have explicitly displayed digits, we can trust them to be correct. If we would carry out the last iteration a bit longer, no correct digit remains. The numbers of the form 0 μ 10n indicate that the result is somewhere in the interval @-10n , +10n D. (Of course, by starting with a higher initial precision we can get verified correct results for any number of iterations.) In[6]:=
Take[modifiedLogisticMapData[N[1/210, 200], 359/100, 2/10, 400, 100], {-45, - 30}] General::unfl : Underflow occurred in computation. More…
Out[6]=
80.4906, 0.8472, 0.491, 0.847, 0.49, 0.85, 0.5, 0.8, 0. × 10−1 , 0., 0., 0. × 101 , 0. × 104 , 0. × 108 , 0. × 1017 , 0. × 1036
10^-30} // N[#, 22]& 5.039811020046271555398× 10−30
The precision model described, generalizes in an obvious way to multivariate functions. Let, for instance, f be a bivariate function of x and y and dx, dy be the uncertainties of the arguments. The uncertainty of the output df ∑ f Hx,yL ∑ f Hx,yL can then be approximated as df º ° ÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅ • dx +° ÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅ • dy. From this follows that the precision of the output ∑x ∑y df df ∑ f Hx,yL ∑ f Hx,yL y dy x dx -log10 ÅÅÅÅÅÅÅÅ Å ÅÅÅ Å Å can be approximated as -log ÅÅÅÅÅÅÅÅ Å ÅÅÅ Å ÅÅ º -log10 I° ÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅ • ÅÅÅÅ ÅÅ +° ÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅ • ÅÅÅÅ ÅÅ M. Here are two 10 f Hx,yL f Hx,yL ∑x f Hx,yL ∑y f Hx,yL x y examples of a built-in bivariate function—arctan and log. In[92]:=
modelPrecision[f_, {x_, y_}, {x0_, y0_}] := (* form symbolic derivatives *) (Abs[D[f[x, y], x] x/f[x, y] 10^-px] + Abs[D[f[x, y], y] y/f[x, y] 10^-py]) /. (* substitute actual values *) {x -> x0, px -> Precision[x0], y -> y0, py -> Precision[y0]} // N // -Log[10, #]&
In[93]:=
Function[{x0, y0}, {Precision[ArcTan[x0, y0]], modelPrecision[ArcTan, {x, y}, {x0, y0}]}][ SetPrecision[10^-50, 20], SetPrecision[2, 30]] 870.4971, 70.4971
{None, Log[10, Select[Denominator[Table[FromContinuedFraction[ Take[ContinuedFraction[ξ, 20], k]], {k, 20}]], (* with relevant denominators *)
1.1 Approximate Numbers
75
(# < Denominator[Rationalize[ξ, 10^-20]])&]] // N}, Axes -> False, DisplayFunction -> Identity, PlotStyle -> {PointSize[0.006]}, Frame -> True, PlotLabel -> InputForm[ξ]]]] /@ (* the two numbers *) {Pi, 1/Pi}]] Pi
Pi^H-1L
10
10
8
8
6
6
4
4
2
2
0
0 0
5
10
15
20
0
5
10
15
20
Here is the concrete example a = 7.8. The fraction returned from Rationalize agrees with the best fraction found by searching and is not a continued fraction convergent. In[47]:=
Out[47]=
{(* use fast Rationalize *) Rationalize[1/Pi, 10^-7.8], (* exhaustive search over all denominators *) Module[{den = 1}, While[δ = Abs[1/Pi - Round[den/Pi]/den]; δ > 10^-7.8, den++]; Round[den/Pi]/den], (* the continued fraction convergents *) Table[FromContinuedFraction[ContinuedFraction[1/Pi, k]], {k, 8}]} 21011 21011 1 7 106 113 33102 33215 66317 9 , , 90, , , , , , , == 66008 66008 3 22 333 355 103993 104348 208341
The pseudoconvergent and the convergent deviate from each other only in the last digit of their continued fraction approximation. And the pseudoconvergent “interpolates” between two continued fraction convergents. In[48]:= Out[48]=
{ContinuedFraction /@ {21011/66008, 33102/103993, 33215/104348}, (* denominator divisibility *) (103993 - 66008)/355} 8880, 3, 7, 15, 1, 185 {GrayLevel[0], PointSize[0.01]}, (* theoretical frequencies *) Prolog -> {Hue[0], Thickness[0.002], Line[Table[{k, -Log[2, 1. - 1/(k + 1)^2]}, {k, 120}]]}]
Numerical Computations
76 0.4
0.3
0.2
0.1
0 0
20
40
60
80
100
Let us analyze the number of times a certain integer appears in the continued fraction approximation of p. We start by calculating 100000 terms of the continued fraction expansion of p. In[52]:= Out[52]=
(cf = ContinuedFraction[Pi, 10^5];) // Timing 80.97 Second, Null
All, PlotJoined -> True, Prolog -> {{Hue[0], Thickness[0.012], Line[Table[{Log[10, k], Log[10, -10^5 Log[2, 1 - 1/(k + 1)^2]]} // N, {k, 10^3}] // N]}}] 10000 1000 100 10 1 1
10
100
1000
10000
100000.
It is conjectured that the same distribution holds for the average over many fractions [96]. Next, we analyze the digits in all proper fractions with denominators less than or equal 1000. This can be done in a fraction of a minute and results in 1784866 continued fraction digits. In[55]:=
(* proper fractions with denominator n *) properNFractions[den_] := Select[Range[den]/den, Denominator[#] == den&]
In[57]:=
(* digit counts of the continued fractions of all proper fractions with denominator n *) cfDigitData[n_] := {First[#], Length[#]}& /@ Split[Sort[Flatten[DeleteCases[ContinuedFraction[#], 0]& /@ properNFractions[n]]]]
In[59]:=
(* function to add counts *) updateCounts[cfDigitData_] := (count[#1] = If[Head[count[#1]] === Integer, count[#1], 0] + #2)& @@@ cfDigitData
In[61]:=
(* analyze all fractions up to denominator 1000 *) Clear[count];
1.1 Approximate Numbers
77
{Do[updateCounts @ cfDigitData[n], {n, 2, 1000}] // Timing, totalDigits = Plus @@ (Last /@ DownValues[count])} 887.37 Second, Null {{0, 200}, All}], (* theoretical distribution *) Plot[Log[1/Log[2] Log[1 + 1/(k k +2)]], {k, 1, 200}, PlotStyle -> {Hue[0]}]}], Frame -> True, Axes -> False] -2 -4 -6 -8 -10 -12 -14 25
50
75
100
125
150
175
200
Unlike decimal fractions, numbers represented as continued fractions are quite unevenly distributed in the real axis. Here, the cumulative probability distribution of all numbers of the form a ê Hb + c ê Hd + eLL, 1 § a, b, c, d, e § 9 are shown. In[65]:=
ListPlot[MapIndexed[{#1, #2[[1]]}&, Sort[Flatten[ Table[(* all continued fractions *) FromContinuedFraction[{0, a, b, c, d, e}], {a, 9}, {b, 9}, {c, 9}, {d, 9}, {e, 9}]]]], PlotStyle -> {PointSize[0.003]}, PlotRange -> All, Axes -> False, Frame -> True] 60000 50000 40000 30000 20000 10000 0 0.2
0.4
0.6
0.8
The following constant is related to continued fractions. Khinchin represents the Khinchin constant K. In[66]:= Out[66]=
N[Khinchin, 22] 2.685452001065306445310
Numerical Computations
78
The importance of this constant stems from the following interesting fact: For almost all real numbers t with the regular continued fraction expansion 1 t = a0 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 1 ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ a1 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 1 a2 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 1 a3 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ a4 + ∫ the following holds [1543], [916] : ¶
log2 k 1 n è!!!!!!!!!!!!!!!!!!!!!!!!! = K = 2.6854… a1 a2 ∫ an =  J1 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅ N nض kHk + 2L
lim
k=1
Let us pick a number at “random”, say, t = fp . We calculate its first 1000 terms of the continued fraction expansion. In[67]:=
cf = Rest @ ContinuedFraction[GoldenRatio^Pi, 1001];
The following graphic shows how the expression In[68]:=
k è!!!!!!!!!!!!!!!!!!!!!!!! a1 a2 ∫ ak behaves [1924], [113].
ListPlot[Table[(Times @@ Take[cf, i])^(1/i), {i, 1000}] // N]
200
400
600
800
1000
2.9 2.8 2.7 2.6 2.5
The next graphic shows means. In[69]:=
n è!!!!!!!!!!!!!!!!!!!!!!!! a1 a2 ∫ an for K itself. This time we use a more efficient procedure to calculate the
cf = Rest @ ContinuedFraction[Khinchin, 4001]; fl = FoldList[(#1^(#2[[1]] - 1) #2[[2]])^(1/#2[[1]])&, 1, Transpose[{Range[4000], N[cf]}]]; ListPlot[fl] 2.8 2.7 2.6 2.5 2.4
1000
2000
3000
4000
In a similar way, the nth root of the denominator of the nth convergent approaches the limit expHp2 ê H12 lnH2LLL . (This fact is the Khinchin–Lévy theorem [1543].)
1.1 Approximate Numbers In[72]:=
79
ListPlot[MapIndexed[#1^(1./#2[[1]])&, Denominator[ Table[FromContinuedFraction[Take[cf, i]], {i, 1000}]]]] 3.3 3.2 3.1
200
400
600
800
1000
2.9 2.8
In[73]:= Out[73]=
Exp[Pi^2/12/Log[2]] // N 3.27582
The expression n ê ⁄nk=1 a-1 k also approaches a universal constant as n Ø ¶ [983]. In[74]:=
ListPlot[MapIndexed[#2[[1]]/#1&, Rest[ FoldList[Plus, 0, 1./Rest[ContinuedFraction[Pi + Log[2] + 3^(1/3), 20000]]]]], Frame -> True, Axes -> False] 1.765 1.76 1.755 1.75 1.745 1.74 1.735 1.73 0
5000
10000
15000
20000
An interesting question about the connection of decimal approximations and continued fraction approximations is the following: Given an n-digit approximation an HxL to an irrational number x, how many terms kn HxL does the continued fraction representation contain on average [1165], [577], [576], [57]? Let us do a numerical experiment with some “random” irrational numbers. In[75]:=
Out[75]=
Length[ContinuedFraction[#]]& /@ N[{Pi, E, Sqrt[2], 3^(1/5), Sin[1/3], Log[7], Tan[1/9], Csc[EulerGamma], Log[Log[Log[100]]], ArcSin[1/2]^ArcSin[1/3]}, 1000] 8967, 603, 1306, 963, 1013, 974, 329, 966, 978, 949
100] 1 0.8 0.6 0.4 0.2 0 0
0.2
0.4
0.6
0.8
1
Numerical Computations
82
Here is a related function. In[89]:=
[n_Integer, x_Real] := FromDigits[{#, 0}, n]& @ Flatten[MapIndexed[Table[n - Mod[#2[[1]], n] - 1, {#1}]&, ContinuedFraction[x]]]
In[90]:=
Plot[Evaluate[Table[[n, ], {n, 2, 12}]], {, 0, 10}, PlotPoints -> 200, PlotRange -> {0, 1}, Frame -> True, Axes -> False, FrameLabel -> {"x", None}, PlotStyle -> Table[Hue[0.8 (n - 2)/12], {n, 2, 12}]] 1 0.8 0.6 0.4 0.2
0
2
4
6
8
10
x
Other applications of continued fractions in numerical analysis can be found in [916]. For doing arithmetic with continued fractions, see [770], [1864]; for differentiation see [1445]. For some very interesting continued fractions, see [985], [1825], and [1428]. For more on continued fractions in Mathematica, see the package Number Theory`ContinuedFractions` and [915] and [1173]. We could also visualize continued fractions by associating with each continued fraction a curve in the complex plane via 1 1 ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ï xHjL = a0 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ Å . x = a0 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 1 1 a1 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ a1 e1 i j + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 1 1 a2 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ a2 e2 i j + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 1 1 a3 + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ a3 e3 i j + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 4ij a4 + ∫ a4 e + ∫ Here are the resulting curves shown for x = e, x = p, x = K, x = 21ê2 , and x = 31ê3 . In[91]:=
cfSpirographGraphic[x_, n_, ϕMax_, pp_, f_:Identity] := Graphics[{PointSize[0.0025], Table[Point[{Im[#], Re[#]}]& @ FromContinuedFraction[ (* parametrized curves *) MapIndexed[N[#1 Exp[f[#2[[1]]] I ϕ]]&, (* cf digits *) ContinuedFraction[x, 10]]], {ϕ, 0, ϕMax, ϕMax/pp}]}, FrameTicks -> None, PlotRange -> Automatic, Frame -> True, AspectRatio -> 1]
In[92]:=
Show[GraphicsArray[cfSpirographGraphic[#, 10, 2Pi, 10000]& /@ (* the five numbers to be used *) {E, Pi, Khinchin, Sqrt[2], 3^(1/3)}]]
1.1 Approximate Numbers
83
The next graphic uses j1ê2 instead of j. As a result, the curves are no longer periodic. In[93]:=
Show[GraphicsArray[cfSpirographGraphic[#, 10, 10 Pi, 20000, Sqrt]& /@ (* the five numbers to be used *) {E, Pi, Pi/E, 3^(1/3), Cos[1]}]]
From a broader context, continued fraction expansions and base b expansions are special cases of iterations of bivariate rational functions rHx, yL [1122], [1232], [1627], [1450], [662], [1231]. rHx, yL = y + 1 ê x results in continued fractions. In[94]:= Out[94]=
Fold[Function[{x, y}, y + 1/x], z5, {z4, z3, z2, z1}] 1 z1 + 1 z2 + 1 z3+ 1 z4+ z5
rHx, yL = y + x ê 10 results in decimal expansions. In[95]:= Out[95]=
Fold[Function[{x, y}, y + x/10], z5, {z4, z3, z2, z1}] // Expand z2 z3 z4 z5 z1 + + + + 10 100 1000 10000
rHx, yL = Hx y + 1L ê Hx - yL results in continued cotHarccotHxL - arccotHyLL [1123], [1645]. In[96]:=
Out[97]=
cotangents.
Hx y + 1L ê Hx - yL
can
be
rewritten
as
Clear[x, y]; Together //@ TrigToExp[Cot[ArcCot[y] - ArcCot[x]]] 1+xy x−y
Here is a “one-line” implementation of the continued cotangent expansion. In[98]:=
ContinuedCotangent[x_, n_] := Cot[Plus @@ MapIndexed[(-1)^(#2[[1]] - 1) #&, ArcCot[Last /@ NestList[Function[{a, b}, {#, Floor[#]}&[(a b + 1)/(a - b)]] @@ #&, {x, Floor[x]}, n]]]]
Here are the first terms of the continued cotangent expansion of Euler’s constant e. In[99]:= Out[99]=
ContinuedCotangent[N[E, 200], 8] Cot@ArcCot@2D − ArcCot@8D + ArcCot@75D − ArcCot@8949D + ArcCot@119646723D − ArcCot@15849841722437093D + ArcCot@708657580163382065836292133774995D − ArcCot@ 529026553215766321676623343348414600292754204772300344704877695232 D + ArcCot@ 515242553865726035688292036059153719454546961626988807336855829294899338742 145207767435587561691068553657192491959216959592398323712DD
Numerical Computations
84
The expansion shows excellent numerical agreement. In[100]:=
N[% - E, 22] 2.670361740169524810912× 10−210
Out[100]=
We now study the rounding of numbers to integers. This is accomplished with Round, Floor, and Ceiling. Round[number] finds the integer that is closest to number.
If number is halfway between two integers and is a fraction (head Rational or Real), Round gives the closest even integer. This happens for exact numbers, machine numbers, and high-precision numbers. In[101]:=
Out[101]=
Union[(Round /@ N[{3/2, 5/2, -3/2, -5/2}, #])& /@ (* exact, machine, and high-precision numbers *) {Infinity, MachinePrecision, $MachinePrecision}] 882, 2, −2, −2 {None, StyleForm[#, FontWeight -> "Bold"]& /@ {"x", "Round[x]", "Floor[x]", "Ceiling[x]"}}, TableAlignments -> {Center, Center}, TableSpacing -> {1, 1}]
Out[102]//TableForm=
x −3 −2.8 −2.5 5 − 2
−2.1 −2 −0.5 1 − 2 0 1 2 0.5 11 10
Round@xD −3 −3 −2 −2 −2 −2 0 0 0 0 0 1
Floor@xD −3 −3 −3 −3 −3 −2 −1 −1 0 0 0 1
Ceiling@xD −3 −2 −2 −2 −2 −2 0 0 0 1 1 2
1.1 Approximate Numbers 3 2
1.5 1.8 2.5
85 2 2 2 2
1 1 1 2
2 2 2 3
We now look at these three functions graphically. In[103]:=
Show[GraphicsArray[ Plot[{x, #[x]}, {x, -3, 3}, DisplayFunction -> Identity, PlotLabel -> StyleForm[ToString[#] "[x]", FontFamily -> "Courier", FontSize -> 5], TextStyle -> {FontWeight -> "Bold", FontSize -> 5}, PlotStyle -> {{Thickness[0.002], Dashing[{0.015, 0.015}]}, {Thickness[0.03]}}]& /@ (* the three functions of interest *) {Round, Floor, Ceiling}]] Round@xD 3
Floor@xD
2 1 -3
-2
-1
-1 -2 -3
Ceiling@xD 3
1 -3 1
2
3
-2
-1
2 1
2
3
1
-1 -2
-3
-2
-1
-3
1
2
3
-1
Here are some more interesting pictures based on the Floor function. We visualize the nontrivial q-fold iterates of the map 8m, n< Ø 8d2 cosH2 p p ê qL mt - n, m< [1176], [1960]. In[104]:=
(* the map *) φ[ν_][{m_, n_}] := {Floor[2 Cos[2 Pi ν] m] - n, m} (* the iterated map *) Φ[ν_Rational][{m0_, n0_}] := Nest[φ[ν], {m0, n0}, Denominator[ν]]
In[108]:=
Show[GraphicsArray[ Graphics[{Thickness[0.002], (* start from all integer pairs within a square *) DeleteCases[Table[Line[{{m0, n0}, Φ[#][{m0, n0}]}], {m0, -40, 40}, {n0, -40, 40}], Line[{a_, a_}], Infinity]}, AspectRatio -> Automatic]& /@ (* three selected p/q *) {1/5, 2/9, 11/14}]]
The Floor and Ceiling functions can be used to construct closed-form expressions for many “unusual” è!!!!!!!!!!!! sequences [1361]. a `2 kp + 1 ê 2q - 1 gives the sequence consisting of one 1, two 2’s, three 3’s and so on. In[109]:=
Table[Ceiling[Sqrt[Ceiling[2k]] + 1/2] - 1, {k, 16}]
Numerical Computations
86 Out[109]=
81, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6
"Courier"], AspectRatio -> Automatic, PlotRange -> {{-6, 6}, {-6, 6}}, Frame -> True, FrameLabel -> {"x", "y"}, GridLines -> ({#, #}&[{#, {GrayLevel[0.7]}}& /@ Range[-6, 6]])]] /@ (* the three integer-valued functions *) {Floor, Ceiling, Round}]] Floor@x + I yD
6
Ceiling@x + I yD
4
4
2
2
2
0
0
0
-2
-2
-2
-4
-4
-4
-4
-2
0 x
2
4
6
-4
-2
0 x
2
Round@x + I yD
6
4
y
y
6
y
In[127]:=
4
6
-4
-2
0 x
2
4
6
After the discussion of the foundations of Rationalize—continued fractions—we will continue to discuss the function Rationalize itself. Let us now use Rationalize to have a closer look at Plus and Times for machine numbers. Machine arithmetic is (in distinction to exact arithmetic) not associative. In the following, we will look for explicit examples of numbers exhibiting this nonassociativeness in Plus and Times. Ratio nalize is a convenient way to test weather two numbers agree in all bits. The following While loop loops until it finds three numbers that exhibit the mentioned nonassociativeness. In[128]:=
SeedRandom[1]; While[a = Random[]; b = Random[]; c = Random[]; ab = a + b; bc = b + c; Rationalize[ab + c, 0] === Rationalize[a + bc, 0], Null]
These are the numbers found. In[130]:=
{a, b, c} // InputForm
Out[130]//InputForm=
{0.12463419022903224, 0.9345372830959425, 0.6002520340808316}
In InputForm, one does not see a difference. In[131]:=
{a + b + c, ab + c, a + bc} // InputForm
Out[131]//InputForm=
{1.6594235074058066, 1.6594235074058066, 1.6594235074058064}
The difference of the two numbers is in their last bit.
1.1 Approximate Numbers In[132]:= Out[132]= In[133]:= Out[133]=
89
{#, N[Subtract @@ #]}& @ Rationalize[{ab + c, a + bc}, 0] 243680247 564919750 99 , =, 2.60046 × 10−16 = 146846327 340431329 #[[3]]& /@ $NumberBits /@ {ab + c, a + bc} 881, 0, 81, 0,
1, 1, 1, 1,
0, 1, 0, 1,
1, 1, 1, 1,
0, 1, 0, 1,
1, 0, 1, 0,
0, 1, 0, 1,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 1, 0,
1, 0, 1, 0,
0, 1, 0, 1,
0, 0, 0, 0,
1, 1, 1, 1,
1, 1, 1, 1,
1, 0, 1, 0,
1, 0, 1, 0,
1, 0, 1, 0,
1, 0, 1, 0,
1, 1, 1, 1,
1, 0, 1, 0,
1, 0, 1, 0,
0, 1, 0, 0,
1, 0, 1, 1,
0, 0, 0, 1,
1, 0, 0 "Courier", FontSize -> 6]];
In[150]:=
Show[GraphicsArray[diffPlot /@ #]]& /@ {{Sin, Log}, {Exp, Sqrt}, {#^3&, 1/(1 + #)&}} Sin
Log
0.75
4 μ 10-14
0.5
2 μ 10-14
0.25 -200
-100
100
200 -200
-0.25
-100
100
200
100
200
100
200
-2 μ 10-14
-0.5 -0.75
Exp
Sqrt
3 0.4
2
0.2
1
-200
-100
100
200
-200
-100
-1
-0.2
-2
-0.4
#1^3 &
1êH1 + #1L &
5 μ 10-11
0.2 0.1
-200
-100 -5 μ 10-11 -1 μ 10-10 -1.5 μ 10-10
100
200 -200
-100 -0.1 -0.2
We conclude this section with an application of Ceiling to Egyptian fractions. Although it has no direct relevance to numerics, it makes heavy use of Ceiling.
1.1 Approximate Numbers
91
Mathematical Application: Egyptian Fractions The ancient Egyptians were familiar only with “unit fractions”, that is, those whose numerator is 1, such as 1 ê 2, 1 ê 3, 1 ê 4, …. General fractions can always be written as sums of distinct unit fractions. Starting with a given fraction p ê q ( p < q), we first find the largest unit fraction 1 ê r less than or equal to p ê q, and write p ê q = 1 ê r + p£ ê q£ . We then repeat this decomposition for p£ ê q£ , p££ ê q££ , etc., until the remainder is 0.
The largest fraction 1 ê r less than or equal to a given fraction p ê q can be found in Mathematica using r = Ceiling[q/p]. Here is the decomposition of a fraction into the largest unit fraction plus a remainder. In[151]:=
fractionDecomposition[0] = 0; fractionDecomposition[pq_Rational?(# < 1&)] := {1/Ceiling[1/pq], pq - 1/Ceiling[1/pq]}
Here is an example. In[153]:= Out[153]=
fractionDecomposition[31/789] 1 17 9 , = 26 20514
Here is a test. In[154]:= Out[154]=
Plus @@ % 31 789
Next, we show the result of repeating this fractional decomposition (until it stops naturally), using fractionDe composition. Observe the use of FixedPointList. At the outset, we do not know how many terms will be needed in the Egyptian decomposition. The use of Drop[…, -2] in the following is necessary to remove the last two zeros. In[155]:=
decomposition[pq_Rational?(# < 1&)] := Drop[FixedPointList[If[# =!= 0, fractionDecomposition[#[[2]]], 0]&, {0, pq} ], -2]
Now, we have the complete decomposition. In[156]:= Out[156]=
{#, (* check *) Plus @@ (First /@ #)}& @ decomposition[31/789] 31 1 17 1 5 9990, =, 9 , =, 9 , =, 789 26 20514 1207 24760398 1 1 1 31 9 , =, 9 , 0==, = 4952080 61307735863920 61307735863920 789
Finally, we have the definition. In[157]:=
EgyptianFractions[pq_Rational?(# < 1&)] := Rest[First /@ decomposition[pq]]
Here is an example illustrating a weak point (at least for practical applications) of EgyptianFractions. In[158]:=
Out[159]=
(ef = EgyptianFractions[36/457]); Take[ef, 6] 1 1 1 1 1 9 , , , , , 13 541 321409 114781617793 14821672255960844346913 1 = 251065106814993628596500876449600804290086881
Numerical Computations
92
For brevity, we display the large integers of the denominators of ef in abbreviated form. where n is an integer with k n decimal digits.
kn
In[160]:=
abbreviateLargeUnitFractions[expr_] := expr //. Rational[1, i_?(# > 10^10&)] :> Subscript[ , Floor[Log[10, i]]]
In[161]:=
ef // abbreviateLargeUnitFractions 1 1 1 , , , 11 , 22 , 44 , 88 , 13 541 321409
Out[161]=
177 ,
355 ,
711 ,
1423 ,
stands for 1 n
2846
This example shows that even for relatively small denominators in the initial fraction, we can get extremely large denominators in the unit fractions. In[162]:= Out[162]=
Length[Last[IntegerDigits[Denominator[ef]]]] 2847
Once again, here is a check. In[163]:= Out[163]=
Plus @@ ef 36 457
It is now not too difficult to find automatically such fractions with huge denominators. For a given set of fractions, we look for those whose last summand is smallest. We take this set of fractions to be those whose denominators are smaller than a prescribed maximum value. In[164]:=
biggestDenominator[maxDenominator_] := (* take "best" one *) #[[1, Position[#[[2]], Min[#[[2]]]][[1, 1]]]]&[ (* EgyptianFraction-ize all fractions *) {#, Last[EgyptianFractions[#]]& /@ #}&[ (* all possible fractions *) Union[Flatten[Table[i/j, {j, maxDenominator}, {i, j - 1}]]]]]
Here is an example. In[165]:= Out[165]= In[166]:= Out[166]=
biggestDenominator[25] 4 25 EgyptianFractions[%] 1 1 1 1 , , , 7 59 5163 53307975
Here is an example showing a denominator with 149 digits. In[167]:= Out[167]=
EgyptianFractions[8/97] 1 1 1 1 , , , , 13 181 38041 1736503177 1 1 , , 3769304102927363485 18943537893793408504192074528154430149 1 , 538286441900380211365817285104907086347439746130226973253778132494225813153 1 5795045870675428017131031918599186082510302919521954235835293576538994186863 42360361798689053273749372615043661810228371898539583862011424993909789665
For fractions with denominators less than 100, 8 97 is “best”—the smallest fraction contains a 150-digit number in its denominator. The representation of a fraction as an Egyptian fraction is not unique; here, the so-called splitting method
1.1 Approximate Numbers
93
[1710], [151] is implemented (the implementation is such that the method becomes obvious; from a computational point of view, it can be considerably accelerated using functions like Split instead of pattern matching of sequences of undetermined length). In[168]:=
EgyptianFractionsViaSplitting[Rational[p_, q_]?Positive] := 1/FixedPoint[Flatten[Sort[# //. {a___, b_, b_, c___} :> {a, b, b + 1, b(b + 1), c}]]&, Table[q, {p}]]
Here is an example and the corresponding result of EgyptianFractions. In[169]:= Out[169]=
In[170]:= Out[170]= In[171]:= Out[171]=
EgyptianFractionsViaSplitting[5/7] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 9 , , , , , , , , , , , , , , , 7 8 9 10 11 56 57 58 59 72 73 74 90 91 110 1 1 1 1 1 1 1 1 1 1 , , , , , , , , , , 3192 3193 3194 3306 3307 3422 5256 5257 5402 8190 1 1 1 1 1 1 , , , , , = 10192056 10192057 10198442 10932942 27630792 103878015699192 Plus @@ % 5 7 EgyptianFractions[5/7] 1 1 1 9 , , = 2 5 70
If one allows negative fractions [1014], it is possible to decompose a given fraction into Egyptian fractions with much smaller denominators. The important function in the following method [220] is the use of Continued Fraction. In[172]:=
EgyptianFractionsViaContinuedFractions[Rational[p_, q_]?Positive] := Module[{makeUnitFraction}, (* extract one unit fraction *) makeUnitFraction[ Rational[1, r_]] := { 1/r}; makeUnitFraction[-Rational[1, r_]] := {-1/r}; makeUnitFraction[f_Rational] := {f - #, #}&[Numerator[#]/Denominator[#]&[ FromContinuedFraction[Take[#, Length[#] - 1]]&[ContinuedFraction[f]]]]; (* iterate the application of makeUnitFraction *) First /@ Rest[NestWhileList[makeUnitFraction[#[[2]]]&, {Null, p/q}, Length[#1] === 2&]]]
Here are some of the above fractions treated with EgyptianFractionsViaContinuedFractions . Now, we get negative fractions and 1, but have much smaller denominators. In[173]:= Out[173]= In[174]:= Out[174]= In[175]:= Out[175]=
{#, Plus @@ #}& @ EgyptianFractionsViaContinuedFractions[5/7] 1 1 5 99 , − , 1=, = 21 3 7 {#, Plus @@ #}& 1 1 99− , =, 1164 12
@ EgyptianFractionsViaContinuedFractions[8/97] 8 = 97
{#, Plus @@ #}& @ EgyptianFractionsViaContinuedFractions[36/457] 1 1 1 1 36 99− , − , , =, = 75405 6270 494 13 457
For more on Egyptian fractions, see [558], [221], [1865], [849], [220], [1714], [1826], [552], and http://www.ics.uci.edu/eppstein/.
Numerical Computations
94
1.1.4 When N Does Not Succeed As already mentioned, N[expression, precision] calculates expression to precision precision. Here is a simple example. In[1]:=
N[(Sqrt[2] - 3)/(Pi + E), 200] −0.270617816556448280260007192492188707145709842225878766679769806431984412532 4485271993747823709967966983358930079614284440691659543581721893374452505679 3693187332135557895453304827109255227475240809358
Out[1]=
In[2]:= Out[2]=
Precision[%] 200.
For the majority of all inputs N will succeed in achieving the required precision. But sometimes it might fail to achieve its goal. Here is a small number representing the difference between p and a rational approximation of p to 100 digits. In[3]:= Out[3]=
diff = SetPrecision[N[Pi, 100], Infinity] - Pi 137429016170745219382391623152025666371669894951468010510891139570723086718398 57418443776796495953395ê 4374501449566023848745004454235242730706338861786424872851541212819905998398 751846447026354046107648− π
Trying to calculate the diff to 100 digits fails. In[4]:=
N[diff, 200] N::meprec : Internal precision limit $MaxExtraPrecision = 50.` reached while evaluating 1374290161707452193823916231520256 33 2308671839857418443776796495953395 − 4374501449566023848745004454235242 32 9905998398751846447026354046107648 π. More…
Out[4]=
8.2855161544410986227684868062404860711073911126741180398326741539381841625705 227177808320431145055254289608412658705178432455732552673429176777482109× 10−101
The function in the message issued by the last input is $MaxExtraPrecision. $MaxExtraPrecision specifies the additional precision, to be used in internal calculations.
The current value of $MaxExtraPrecision is 50 (compared to the default value infinity of $MaxPrecision). In[5]:= Out[5]=
$MaxExtraPrecision 50.
If we increase this value, we can calculate the diff to 100 digits. In[6]:= Out[7]=
$MaxExtraPrecision = 200; N[diff, 200] 8.2855161544410986227684868062404860711073911126741180398326741539381841625705 22717780832043114505525428960841265870517843245573255267342917677748210922481 0506766766020508507701288360905492084476752783× 10−101
1.1 Approximate Numbers
95
The following input defines a function lowerPrecision that returns a number with a much lower precision than its input. Printing the precision of the input allows us to monitor the way Mathematica internally tries to increase the precision of the input to achieve the required precision. In[8]:=
$MaxExtraPrecision = 20000; SetAttributes[lowerPrecision, NumericFunction]; lowerPrecision[x_?InexactNumberQ] := (Print[Precision[x]]; (* output precision is a slowly increasing function of input precision *) SetPrecision[x, Round[Sqrt[Precision[x]]]]); (* try to obtain the function value at 1 to 100 digits *) N[lowerPrecision[1], 100] 100. 209.934 429.802 869.538 1749.01 3507.95 7025.84 9277.89 10029.2
Out[13]=
1.0000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000
For expressions that are not functions, we cannot use the NumericFunction attribute. In such cases, we can directly set the NumericQ property. A typical situation are symbolic derivatives of functions. Numerical techniques, including $MaxExtraPrecision are not only used in N, but in some other functions, such as Equal, Less, Greater, Floor, Ceiling, and so on. The next input shows that the numerical comparison functions (like Less) also use numerical techniques. In[14]:= Out[15]=
$MaxExtraPrecision = 50; E < 100286898419598513365/36893488147419103232 False
A mathematical equality of not structurally-identical exact quantities can never return True based on numerical verification methods. Numericalization can only show that an equality does not hold. With the default setting of $MaxExtraPrecision, Mathematica cannot prove by validated numericalization that the left-hand side and the right-hand side are numerically different. In[16]:=
EA = Rationalize[E, 10^-80]; E == EA N::meprec : Internal precision limit $MaxExtraPrecision = 50.` reached 98365108381354828986614872525724254586156 while evaluating − + . More… 36186501102101171855141260988678169767695
Numerical Computations
96 Out[17]=
98365108381354828986614872525724254586156
36186501102101171855141260988678169767695
The left-hand side of the following equation is identically zero. In[18]:=
Sqrt[2] + Sqrt[3] - Sqrt[5 + 2 Sqrt[6]] == 0 N::meprec : Internal precision limit $MaxExtraPrecision = è!!!!! è!!!!! "######################## è!!!!! 50.` reached while evaluating 2 + 3 − 5 + 2 6 . More…
Out[18]=
è!!!! è!!!! "##################### è!!!! 2 + 3 − 5+2 6 0
Because the precision of (the numerically calculated) 0 is always zero and not a single significant digit can be found, increasing $MaxExtraPrecision does not help in this example. In[19]:=
$MaxExtraPrecision = 500; Sqrt[2] + Sqrt[3] - Sqrt[5 + 2 Sqrt[6]] == 0 N::meprec : Internal precision limit $MaxExtraPrecision = è!!!!! è!!!!! "######################## è!!!!! 500.` reached while evaluating 2 + 3 − 5 + 2 6 . More…
Out[20]=
è!!!! è!!!! "##################### è!!!! 2 + 3 − 5+2 6 0
If one writes routines for numerical calculation, it is often useful to make leverage from the built-in precision-raising mechanism of N. The following function badlyConditioned mimics a (potentially large) calculation in which a lot of precision is lost. We restrict its input to approximative numbers. (For exact input, many numerical routines will take a much longer time.) In[21]:=
$MaxExtraPrecision = 50; badlyConditioned[x_?InexactNumberQ] := SetPrecision[x, Precision[x]/2]
Now, we try to get a 100-digit result for badlyConditioned[2]. In[23]:=
N[badlyConditioned[2], 100] N::meprec : Internal precision limit $MaxExtraPrecision = 50.` reached while evaluating badlyConditioned@2D. More…
Out[23]=
2.00000000000000000000000000000000000000000000000000000000000000000000000000
It did not work! In[24]:= Out[24]=
Precision[%] 75.
Why? N numericalizes on numeric quantities properly, but badlyConditioned[2] is not a numeric quantity. In[25]:= Out[25]=
NumericQ[badlyConditioned[2]] False
This means we must give the function badlyConditioned the attribute NumericFunction. In[26]:=
Remove[badlyConditioned]; SetAttributes[badlyConditioned, NumericFunction]; badlyConditioned[x_?InexactNumberQ] := SetPrecision[x, Precision[x]/2]
Now, badlyConditioned[2] is a numeric object. In[29]:= Out[29]=
NumericQ[badlyConditioned[2]] True
1.1 Approximate Numbers
97
The built-in precision-raising technology now goes to work. In[30]:=
N[badlyConditioned[2], 100] N::meprec : Internal precision limit $MaxExtraPrecision = 50.` reached while evaluating badlyConditioned@2D. More…
Out[30]= In[31]:= Out[31]=
2.00000000000000000000000000000000000000000000000000000000000000000000000000 Precision[%] 75.
We did not succeed in getting the required precision, but this can now be cured by raising the value of $MaxEx traPrecision. In[32]:= Out[33]=
In[34]:= Out[34]=
$MaxExtraPrecision = 200; N[badlyConditioned[2], 100] 2.0000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000 Precision[%] 100.
Sometimes when dealing a lot with high-precision numbers, it might occur that the same calculation gives different results when carried out at different times. Let us construct such a situation. We start with an expression that is numerically zero. In[35]:=
zero = Sin[Pi/32] - Sqrt[2 - Sqrt[2 + Sqrt[2 + Sqrt[2]]]]/2;
Adding a small rational number to zero and testing if the resulting expression is identically zero does not succeed with the default value of $MaxExtraPrecision. In[36]:=
$MaxExtraPrecision = 50; zero + 10^-100 == 0 N::meprec : Internal precision limit $MaxExtraPrecision = 50.` reached while evaluating 1 − 1000000000000000000000000000000000 33 0000000000000000000000000000000000 1 "############################################################### π è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!# 2 − 2 + Power@2D + SinA E. More… 2 32
Out[37]=
1ê 100000000000000000000000000000000000000000000000000000000000000000000000000 1 π "################# è!!!! 00000000000000000000000000− &''''''''''''''''''''''''''''''''''''''''''''' 2 − $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 + 2 + 2 % + SinA E 0 2 32
Now, we temporarily set $MaxExtraPrecision to a higher value and calculate a 500-digit approximation of zero + 10^-100. In[38]:= Out[39]=
$MaxExtraPrecision = 2000; N[zero + 10^-100, 500] 1.0000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000× 10−100
Numerical Computations
98 In[40]:= Out[40]=
zero
+ 10^-100 == 0
False
Now, we are setting the value of $MaxExtraPrecision back to 50. In[41]:=
$MaxExtraPrecision = 50; zero + 10^-100 == 0 N::meprec : Internal precision limit $MaxExtraPrecision = 50.` reached while evaluating 1 − 1000000000000000000000000000000000 33 0000000000000000000000000000000000 1 "############################################################### π è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!# 2 − 2 + Power@2D + SinA E. More… 2 32
Out[42]=
1ê 100000000000000000000000000000000000000000000000000000000000000000000000000 1 π "################# è!!!! 00000000000000000000000000− &''''''''''''''''''''''''''''''''''''''''''''' 2 − $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 + 2 + 2 % + SinA E 0 2 32
Mathematica keeps internal cache tables with certain symbolic and numeric quantities that it has already calculated. Often, this caching of values is quite useful and can reduce timings considerably. In the following two inputs, the real work is done only once. In[43]:= Out[43]= In[44]:= Out[44]=
N[Pi, 100000]; // Timing 80.37 Second, Null< N[Pi, 100000]; // Timing 80. Second, Null
{Hue[0], Thickness[0.016]}], (* approximation as red points *) ListPlot[MapIndexed[{-10 + #2[[1]]/512 20, #1}&, #[approxFT]]]}, PlotRange -> All, Frame -> True, Axes -> False]]& /@ {Re, Im}]] 0.8 1.5 μ 10-15
0.6
1 μ 10-15
0.4
5 μ 10-16 0.2
0
0
-5 μ 10-16 -10
-5
0
5
10
-10
-5
0
5
10
Let us use the function Fourier to produce some more pictures. Here is a contour plot of a product of 30 implicitly given circles of random midpoints and radii. In[99]:=
SeedRandom[55555]; circles = Table[Circle[{Random[], Random[]}, Random[]], {30}];
In[101]:=
product[x_, y_] = Times @@ Apply[(x - #1[[1]])^2 + (y - #1[[2]])^2 - #2^2&, circles, {1}];
In[102]:=
cp = ContourPlot[Evaluate[product[x, y]], {x, 0, 1}, {y, 0, 1}, Contours -> {0}, PlotPoints -> 401, Frame -> None, Epilog -> {Hue[0], Thickness[0.002], circles}]
Numerical Computations
250
We extract the data from the last picture (an array of 400 μ 400 real numbers) and display the same picture (now looking a bit grainier) as a density graphics. The matrix data is a 400 μ 400 array of ±1. In[103]:=
ListDensityPlot[data = Sign[cp[[1]]], Mesh -> False, Frame -> None]
ftData is the Fourier transform of data. In[104]:=
ftData = Fourier[data];
The function ftPicture basically displays the first n Fourier coefficients of data. In[105]:=
ftPicture[n_, f_, opts___] := ListDensityPlot[f[InverseFourier[ MapIndexed[If[Max[#2] > n, 0., #1]&, ftData, {2}]]], opts, Mesh -> False, Frame -> False]
Taking more and more Fourier coefficients and using the real parts shows nicely how the original picture reemerges. In[106]:=
Show[GraphicsArray[#]]& /@ Partition[ftPicture[#, Re, DisplayFunction -> Identity]& /@ {10, 50, 100, 200, 300, 350, 390, 399, 400}, 3]
1.5 Fourier Transforms
251
But also, the imaginary part, the absolute value, and even the argument contain visually recognizable information of our circles. In[107]:=
Show[GraphicsArray[ Block[{$DisplayFunction = Identity}, {ftPicture[300, Im], ftPicture[380, Abs]}]]]
In[108]:=
Show[GraphicsArray[ ftPicture[#, Arg, DisplayFunction -> Identity]& /@ {10, 100, 360, 390}]]
Numerical Computations
252
For some application of Fourier transforms in optics, including further interesting pictures, see [1158] and [790]. Sometimes, one is interested in the real symmetric part; for details of the corresponding discrete Fourier cos transform, see [1721]. Two closely related functions to Fourier and InverseFourier are ListConvolve and ListCorre late [1917]. ListConvolve[kernel, data] calculates the convolution of the lists kernel and data.
For a 1D list data of the form {x1 , x2 , …, xn } and a kernel of the form {y1 , y2 , …, ym }, the elements zk of the convolution 8z1 , z2 , …, zn-m+1 < are zk = ⁄mj=1 y j xk- j . Here is a simple symbolic example. In[109]:=
ListConvolve[Table[k[i], {i, 3}], Table[a[i], {i, 8}]] 8a@3D k@1D + a@2D k@2D + a@1D k@3D, a@4D k@1D + a@3D k@2D + a@2D k@3D, a@5D k@1D + a@4D k@2D + a@3D k@3D, a@6D k@1D + a@5D k@2D + a@4D k@3D, a@7D k@1D + a@6D k@2D + a@5D k@3D, a@8D k@1D + a@7D k@2D + a@6D k@3D
True]]]
Numerical Computations
256
1 0.8 0.6 0.4 0.2
3.2
3.4
3.6
3.8
4
4.2
4.4
Next, we consider the random sequence sk = s jHkL + 1, s0 = 0, where sH jL is a random integer from the interval @0, k - 1D [176], [1623]. We calculate the average over 1000 realizations of sequences of length 1000. In[130]:=
SeedRandom[50]; randomSequenceAverages = Module[{o = 10^3, m = 10^3, L}, Sum[L = Table[0, {k, o}]; Do[L[[n]] = L[[Random[Integer, {1, n - 1}]]] + 1, {n, 2, o}]; L, {m}]/m];
A graphic of the average sequence terms suggests a logarithmic growth sêêêk ~ lnHkL. In[132]:=
ListPlot[randomSequenceAverages]
7
6
5
200
400
600
800
1000
We average the differences dsk = sk - lnHkL with convolution kernels of increasing width. In[133]:=
(* differences to Log[k] *) δrandomSequenceAverages = Rest[randomSequenceAverages] Log[Range[Length[randomSequenceAverages] - 1]] // N;
In[135]:=
Module[{lc, m = Length[δrandomSequenceAverages]/2}, (* make graphics *) Show[Graphics[{PointSize[0.006], (* form averages *) Table[lc = ListConvolve[Table[1/(2j + 1), {2 j + 1}], δrandomSequenceAverages]; {Hue[0.78 j/m], MapIndexed[Point[{#2[[1]] + j + 1, #1}]&, lc]}, {j, 0, m, 5}]}], Frame -> True]]
1.5 Fourier Transforms
257
0.585
0.58
0.575
0.57
0.565 0
200
400
600
800
1000
The last graphic suggests that sêêêk = lnHkL + g. Forming the average over all averages series terms yields the value of g within 0.004%. In[136]:= Out[136]=
1 - EulerGamma /(Total[δrandomSequenceAverages]/ (Length[δrandomSequenceAverages] + 1)) −0.0000365355
The second function related to Fourier and InverseFourier is ListCorrelate. ListCorrelate[kernel, data] calculates the correlation of the lists kernel and data.
For a 1D data list of the form {x1 , x2 , …, xn } and a kernel of the form {y1 , y2 , …, ym }, the elements zk of the correlation 8z1 , z2 , …, zn-m+1 < are zk = ⁄mj=1 y j xk+ j . Here are the two examples from above used in ListCorrelate instead of ListConvolve. Again, the arguments can be tensors of any rank. In[137]:= Out[137]=
In[138]:= Out[138]=
ListCorrelate[Table[k[i], {i, 3}], Table[a[i], {i, 8}]] 8a@1D k@1D + a@2D k@2D + a@3D k@3D, a@2D k@1D + a@3D k@2D + a@4D k@3D, a@3D k@1D + a@4D k@2D + a@5D k@3D, a@4D k@1D + a@5D k@2D + a@6D k@3D, a@5D k@1D + a@6D k@2D + a@7D k@3D, a@6D k@1D + a@7D k@2D + a@8D k@3D< ListCorrelate[Table[k[i, j], {i, 3}, {j, 3}], Table[a[i, j], {i, 4}, {j, 4}]] 88a@1, 1D k@1, 1D + a@1, 2D k@1, 2D + a@1, 3D k@1, 3D + a@2, 1D k@2, 1D + a@2, 2D k@2, 2D + a@2, 3D k@2, 3D + a@3, 1D k@3, 1D + a@3, 2D k@3, 2D + a@3, 3D k@3, 3D, a@1, 2D k@1, 1D + a@1, 3D k@1, 2D + a@1, 4D k@1, 3D + a@2, 2D k@2, 1D + a@2, 3D k@2, 2D + a@2, 4D k@2, 3D + a@3, 2D k@3, 1D + a@3, 3D k@3, 2D + a@3, 4D k@3, 3D None, DisplayFunction -> Identity]] In[140]:=
(* show resulting graphic for three trigonometric products *) Show[GraphicsArray[ {lcGraphics[Cos[x] Cos[y], {x, y}, { 1, 4}], lcGraphics[Cos[x] Cos[y], {x, y}, { 1, 10}], lcGraphics[Sin[x] Sin[y], {x, y}, {3/2, 10}]}]]
Here is a more interesting looking kernel. Because of the singularities of the tangent function, some elements are weighted much more. This time we use ListCorrelate. In[142]:=
Show[GraphicsArray[ Apply[Function[{β, α}, ListDensityPlot[ListCorrelate[ N[Table[Tan[x] Cot[y], {x, -α Pi, α Pi, 2α Pi/β}, {y, -α Pi, α Pi, 2α Pi/β}]], data], Mesh -> False, ColorFunction -> GrayLevel, Frame -> None, DisplayFunction -> Identity]], (* three sets of parameters *) {{11, 0.49999}, {11, 0.99999}, {30, 0.49999}}, {1}]]]
The following three pictures have random kernels. We display them using the color function Hue. ListCorre late and ListConvolve produce similar pictures. In[143]:=
Show[GraphicsArray[ ListDensityPlot[ListCorrelate[Table[Random[Real, {-1, 1}], {#}, {#}], data], Mesh -> False, Frame -> None, ColorFunction -> (Hue[2#]&), DisplayFunction -> Identity]& /@ {4, 8, 16, 32}]]
1.5 Fourier Transforms
259
Here are three individual convolutions with kernels of different size. To obtain matrices of the same size, we pad cyclically. We display them in one picture using the array values inside RGBColor. The right graphic uses a kernel that contains a dominating smooth part and a small fluctuating part. In[144]:=
Show[GraphicsArray[ {(* different kernels for red, green blue part *) Graphics[Raster[Transpose[ ListConvolve[Table[Random[Real, {-1, 1}], {#}, {#}], data, 4]& /@ {8, 16, 32}, {3, 1, 2}], ColorFunction -> RGBColor], AspectRatio -> Automatic], (* kernel with small fluctuating part *) With[{pp = 24, α = 3/2}, kernel = Table[Cos[x y] + Random[Real, {-1, 1}]/3, {x, -α Pi, α Pi, 2 α Pi/pp}, {y, -α Pi, α Pi, 2 α Pi/pp}] // N; ListDensityPlot[ListCorrelate[kernel, data], Mesh -> False, Frame -> None, DisplayFunction -> identity, ColorFunction -> (Hue[1.6 #]&)]]}]]
We end this set of graphic examples with some more variations of kernels. In[145]:=
Show[GraphicsArray[ ListDensityPlot[ListConvolve[#, data], Mesh -> False, Frame -> None, ColorFunction -> Hue, DisplayFunction -> Identity]& /@ (* three different kernels *) N[{Table[-1^(i + j), {i, 6}, {j, 6}], Table[1/(i^2 + j^2 + 10), {i, -14, 14}, {j, -14, 14}], Table[Sin[i j] i j, {i, -14, 14}, {j, -14, 14}]}]]]
Numerical Computations
260
Many more interesting graphics can be generated using Fourier and ListConvolve [531]. Besides starting from an array of gray levels or colors, a wide range of possibilities opens when we convert generic Mathematica graphics into bitmaps and then use the bitmap data within ListConvolve. The next picture does this with the expression ei p . The resulting gray level values are interpreted as heights for a 3D graphic. In[146]:=
Module[{n = 25, data, kernel, lc, polys}, (* rasterize graphics *) data = ImportString[ExportString[Graphics[ {Text[StyleForm[(* the expression Exp[I Pi] *)"\!\(e\^\(i π\)\)", FontSize -> 180, FontWeight -> "Plain"], {0, 0}]}, AspectRatio -> 1, ColorOutput -> GrayLevel, FormatType -> TraditionalForm], "PGM", ImageResolution -> 63], "PGM"][[1, 1]]; (* the smoothing kernel *) kernel = Table[-(Abs[n - i]^2 + Abs[n - j]^2 + 0.5)^(-0.7), {i, 2n - 1}, {j, 2n - 1}]; If[Length[Dimensions[data]] == 3, data = Map[First, data, {2}]]; (* the smoothed data *) lc = 0.8 #/Max[#]&[(# - Min[#])&[ListConvolve[kernel, N[data]]]]; (* make 3D polygons *) polys = Cases[Graphics3D[ListPlot3D[lc, Mesh -> False, PlotRange -> All, DisplayFunction -> Identity]], _Polygon, Infinity]; (* display smoothed 3D expression *) Show[Graphics3D[{EdgeForm[], {SurfaceColor[Hue[#[[3]]], Hue[#[[3]]], 2.6]&[ Plus @@ #[[1]]/4], #}& /@ polys}], Boxed -> False, BoxRatios -> {1, 1, 0.5}, ViewPoint -> {-1, 0.2, 3}, PlotRange -> All, ViewVertical -> {0, 1, 0}]]
Here is a more complex picture using trigonometric identities.
1.5 Fourier Transforms Make Input
Off[N::"meprec"]; SeedRandom[314159265358979323846]; Module[{makeRaster, randomNontrivialIdentity, gr, tab, dimx, dimy, pos1, pos2, data}, (* bitmap make from Graphics *) makeRaster[gr_Graphics, r_Integer] := ImportString[ExportString[gr, "PGM", ImageResolution -> r], "PGM"][[1]]; (* random trigonometric identity *) randomNontrivialIdentity := Module[{randomIdentity}, randomIdentity := Module[{r, e}, r = {3, 4, 5, 6, 8, 12, 15, 20}[[ Random[Integer, {1, 8}]]]; e = Exp[I Random[Integer, {1, r - 1}]/r Pi]; e == FunctionExpand[ExpToTrig[e]]]; While[e = randomIdentity, Null]; e]; (* a collection of identities *) gr = Show[Graphics[ Table[{GrayLevel[Random[]], Text[StyleForm[ (* avoid evaluation *) Function[c, ToString[Unevaluated[c], StandardForm], {HoldAll}] @@ randomNontrivialIdentity, FontSize -> Random[Integer, {4, 20}], FontWeight -> "Bold"], {Random[], Random[]}]}, {120}]], DisplayFunction -> Identity]; (* making a bitmap *) tab = makeRaster[gr, 120]; (* extracting interesting parts *) {dimx, dimy} = tab[[2, 2]]; cM = tab[[3, 2]]; pos1 = Position[tab[[1]], _?(# =!= cM&), {2}, 1, Heads -> False][[1, 1]]; pos2 = dimy - Position[Reverse[tab[[1]]], _?(# =!= cM&), {2}, 1, Heads -> False][[1, 1]]; data = Map[(* color or gray? *) If[Head[#] === List, First[#], #]&, Take[tab[[1]], {pos1, pos2}, {1, pos2 - pos1 + 1}], {2}]; (* display original and Listconvolve'd version *) Show[GraphicsArray[ ListDensityPlot[#, DisplayFunction -> Identity, FrameTicks -> None, Mesh -> False, AspectRatio -> 1, ColorFunction -> (Hue[2#]&)]& /@ {Reverse /@ data, ListConvolve[Table[1., {3}, {3}], data]}]]]
261
Numerical Computations
262
Convolutions are sometimes also useful for manipulating 3D graphics. Here is a random curve in 3 . In[147]:=
SeedRandom[987654321]; With[{n = 8}, curve[t_] = Table[Sum[Random[Real, {-1, 1}] Cos[i t + 2Pi Random[]], {i, n}], {3}]];
We discretize the curve using 250 points. In[149]:=
data = Table[Evaluate[curve[t]], {t, 0., 2.Pi, 2.Pi/250}];
We smooth (and contract) the curve by averaging over sets of five neighboring points. ListConvolve allows us to do this averaging process quickly. In[150]:=
uniformKernel = Table[1, {5}]/5;
In[151]:=
mesh = Append[#, First[#]]& /@ NestList[ Function[data, Transpose[ListConvolve[ (* the structured kernel *) uniformKernel, #, 3]& /@ Transpose[data]]], data, 100];
In[152]:=
Show[Graphics3D[{Thickness[0.002], MapIndexed[{Hue[#2[[1]]/120], Line[#]}&, mesh]}], Boxed -> False, PlotRange -> All]
Next, we use a convolution kernel with seven random elements. As a result, the curve still shrinks, but as smoothly as before. In[153]:=
randomKernel = #/Plus @@ #&[Table[Random[], {7}]];
In[154]:=
mesh = Append[#, First[#]]& /@ NestList[ Function[data, Transpose[ListConvolve[(* the random kernel *) randomKernel, #, 4]& /@ Transpose[data]]], data, 100];
In[155]:=
Show[GraphicsArray[ Graphics3D[{Thickness[0.002],
1.5 Fourier Transforms
263
MapIndexed[{Hue[#2[[1]]/120], Line[#]}&, #]}, Boxed -> False, PlotRange -> All]& /@ {mesh, Transpose[mesh]}]]
There are, similar to convolutions, many relations between the Fourier transform and the correlation of a list. One is the fact that the autocorrelation list is (modulo a prefactor) just the inverse Fourier transform of the square of the absolute value of the Fourier transform of a list. Here is a random walk. The local stepping direction is within a cone of the direction of the last step. In[156]:=
SeedRandom[54321]; walk1 = Module[{δω = 1., dir = {1, 0}}, NestList[((* the new direction *) dir = {{Cos[#], Sin[#]}, {-Sin[#], Cos[#]}}&[ Random[Real, {-δω, δω}]].dir; (* new step *) # + dir)&, {0, 0}, 2^12]];
In[158]:=
Show[Graphics[Line[walk1]], PlotRange -> All, Frame -> True] 120 100 80 60 40 20 0 -20 -25
0
25
50
75
100
125
150
Here is the autocorrelation function of the x-values of the walk calculated in the two described ways. In[159]:=
Show[ Block[{xWalk1 = First /@ walk1, $DisplayFunction = Identity}, GraphicsArray[ {(* autocorrelation calculated as correlation *) ListPlot[ListCorrelate[xWalk1, xWalk1, 1]], (* autocorrelation calculated as inverse Fourier transform *) ListPlot[Sqrt[Length[xWalk1]]* InverseFourier[Abs[Fourier[xWalk1]]^2]]}]]]
Numerical Computations
264
1.6 μ 107
1.6 μ 107
1.5 μ 107
1.5 μ 107
1.4 μ 107
1.4 μ 107
1.3 μ 107
1.3 μ 107 1000
2000
3000
4000
1000
2000
3000
4000
1.6 Numerical Functions and Their Options The most important numerical functions for numerical summation (NSum), numerical product formation (NProduct), numerical integration (NIntegrate), numerical equation solving (FindRoot), numerical minimization (FindMinimum, NMinimize), and numerical differential equation solving (NDSolve) have a good amount of options to control their behavior in detail. In[1]:=
numericalFunctions = {NSum, NProduct, NIntegrate, FindRoot, FindMinimum, NMinimize, NDSolve};
In[2]:=
{#, Length[Options[#]]}& /@ numericalFunctions 88NSum, 10 {0.0}, MaxRecursion -> 1, PlotPoints -> {{6, 5}, {6, 5}, {12, 5}}]. b) Make a pretty picture of the surface defined by the implicit equation
32 - 216 x2 + 648 x2 y - 216 y2 - 216 y3 - 150 z + 216 x2 z + 216 y2 z + 231 z2 - 113 z3 = 0 using ContourPlot3D and using the symmetry of the surface. Try to make the picture of this surface without using ContourPlot3D. c) Given the following definitions (after loading the package Graphics`Polyhedra`):
polyWithPlatoSymmetry[plato_, {x_, y_, z_}, n_] := Plus @@ (({x, y, z}.#)^n & /@ ((Plus @@ #/Length[#]& /@ (First /@ (Polyhedron[plato][[1]]))))) - 1 dodePoly = Chop[polyWithPlatoSymmetry[Dodecahedron, {x, y, z}, 14]] cylinderAxisDirections = #/Sqrt[#.#]& /@ Chop[Apply[Plus, First /@ Take[Polyhedron[Dodecahedron][[1]], 6], {1}]/5] cylinderPoly = Times @@ (x^2 + y^2 + z^2 - ({x, y, z}.#)^2 - 0.01 & /@ cylinderAxisDirections); thePoly[{x_, y_, z_}] = dodePoly cylinderPoly + 3 10^-2; What is the form of the surface implicitly defined by thePoly[{x, y, z}] == 0? Make a picture of the inner part of this surface without using ContourPlot3D.
Exercises
527
d) Construct a thickened wireframe version of a dodecahedron made from triangles. The polygonal mesh
forming the thickened wireframe should have at least 104 triangles. Smooth the thickened wireframe by replacing the coordinates of each point with the average of all neighboring points. Iterate this smoothing procedure 1000 times. 8.L1 A Convergent Sequence for p, Contracting Interval Map a) Investigate the convergence of the sequence 1 ê an to p, where
yn+1 an+1 y0 a0
4 1 - y4n# 1 - "############## = ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 4 1 + "############## 1 - y4n#
4
= H1 + yn+1 L an - 22 n+3 yn+1 H1 + yn+1 + y2n+1 L è!!!! = 2 -1 è!!!! = 6-4 2.
Do the same for the following sequence. yn+1 un
25 v2n = ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅ Hv2n + un + vn L2 yn 5 = ÅÅÅÅÅÅÅÅÅ - 1 yn
y0
un "############################################### # 2 5 ÅÅÅÅÅÅÅÅÅ JHu - 1L2 + 7 + = $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% HHun - 1L2 + 7L - 4 u3n N % n 2 5n = y2n an - ÅÅÅÅÅÅÅÅÅ Jy2n - 5 - 2 "#################################### yn Hy2n - 2 yn + 5L#N 2 è!!!! = 5 I 5 - 2M
a0
1 = ÅÅÅÅÅ . 2
vn an+1
For derivations of these iterations, see [114], [247], [864]. b) Consider the map x Ø 8a x + b< with 0 < a, b < 1 and 8x< denoting the fractional part of x [313]. Starting with the interval @0, 1D, visualize the repeated application of the map for various a, b .
9.L1 Standard Map, Stochastic Webs, Iterated Cubics, Hénon Map, Triangle Map a) The so-called standard mapping is an iterative mapping of H0, 1LäH0, 1L into itself. It is defined by
K xi+1 = Jxi + yi - ÅÅÅÅÅÅÅÅÅÅ sinH2 p xi LN mod 1 2p K yi+1 = Jyi - ÅÅÅÅÅÅÅÅÅÅ sinH2 p xi LN mod 1. 2p Depending on the choice of K and the starting point 8x0 , y0 False];
Exercises
529
shows four nearly parallel “lines” for 5500 d n d 8500. Are these nearly parallel “lines” numerical artifacts or are they real? If they are real, find other k, 8x0 , y0 False, Axes -> False]; f) Given a random trigonometric function (such as
Sum[Random[] Cos[i x + 2 Pi Random[]] Cos[j y + 2 Pi Random[]], {i, 0, n}, {j, 0, n}]) calculate curves that start and end at extremal points and follow the gradient. g) Make an animation that shows the equipotential lines of two superimposed finite square (hexagonal) grids
made from line segments. Let the angle the two grids form be the animation parameter. Try for an efficient implementation. 11.L2 A Ruler on the Fingers, Trajectories in Highly Oscillating Potential, Branched Flows a) Describe the following experiment via a numerical solution of Newton’s equation of motion. Hold a ruler
horizontally on your index fingers (about 20 to 40 cm apart). Now move the fingers horizontally toward each other at a nearly uniform velocity. This causes the ruler to move alternately left and right. In computing the solution of this problem, be especially careful where the direction of movement changes. What would be the result if there were no static friction?
Numerical Computations
532
b) Calculate and visualize 100 trajectories (with randomly chosen initial conditions) of a particle moving in the
2D potential V Hx, yL = sinHcotHy - x2 L + tanHx + yLL. c) Visualize the motion of many particles moving under the simultaneous influence of a smooth, random
potential and a monotonic potential. 12.L1 Maxwell’s Line, Quartic Determinant a) Plot the isothermals of a van der Waal’s gas on a p,V -diagram (compute Maxwell’s line). For details on the
construction of Maxwell’s line, see, for example, [853], [1417], [301], [1073], [1871], [79], and [640]. For a general treatment of van der Waal’s gas, see [1814], [928], [816], [817], and [4]. b) Calculate realizations for ai, j , bi, j , and ci, j such that the following determinantal identity holds [533]:
ƒƒi 0 a1,2 x + b1,2 y + c1,2 z a1,3 x + b1,3 y + c1,3 z a1,4 x + b1,4 y + c1,4 z yƒƒƒ ƒƒj zzƒƒ ƒƒjj ƒƒjj a1,2 x + b1,2 y + c1,2 z 0 a2,3 x + b2,3 y + c2,3 z a2,4 x + b2,4 y + c2,4 z zzzzƒƒƒ j z§ = †ƒjjj 0 a3,4 x + b3,4 y + c3,4 z zzzzƒƒƒ ƒƒjj a1,3 x + b1,3 y + c1,3 z a2,3 x + b2,3 y + c2,3 z ƒƒjj zzƒƒƒ ƒƒ a1,4 x + b1,4 y + c1,4 z a2,4 x + b2,4 y + c2,4 z a3,4 x + b3,4 y + c3,4 z 0 ƒk {ƒƒ 2 i Hx4 + y4 + z4 L. It is known that some of the ai, j , bi, j , and ci, j are ≤1. 13.L2 Smoothing Functions, Secant Method Iterations, Unit Sphere Inside a Unit Cube a) Plot the function ¶
he HxL = ‡
ge HyL f Hx - yL dy
-¶
with e l o expH1 ê Hx2 - e2 LL ê Ÿ-e expH1 ê Hx2 - e2 LL dx ge HxL = m o0 n l sinHxL 0 § x § 2 p o f HxL = m o0 otherwise n
-e § x § e otherwise
for e = 4, 2, 1, 1 ê 2, 0 § x § 2 p. Be careful that no error messages are generated during the computation. b) How does the pattern in the following graphic arise?
DensityPlot[x /. FindRoot[Cos[x] - x, {x, x1, x2}, Method -> Secant, MaxIterations -> 30], {x1, -10, 10}, {x2, -10, 10}, Compiled -> False, PlotPoints -> 200, Mesh -> False, ColorFunction -> (Hue[0.8 #]&)] c) The part d HrL of a dD sphere of radius r that is inside a dD unit cube centered at the origin (and, without loss
of generality, oriented along the coordinate axes) is given by d HrL = ‡
1ê2
1ê2
‡
-1ê2 -1ê2
∫‡
1ê2 -1ê2
dJr - "##################################### x21 + x22 + … + x2d# N dx1 dx2 … dxd .
Exercises
533
Integrating the Dirac delta function gives the following recursion relation for the area [1028] minHr,Hd-1L1ê2 ê2L
d HrL = 2 r
‡ maxI0,Hr2 -1ê4L1ê2 M
d-1 HL ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ d. è!!!!!!!!!!!!!!!! r2 - 2
Starting with 1 HrL = 2 qHrL qH1 ê 2 - rL, calculate numerically and visualize d HrL for 1 § d § 25. 14.L1 Computation of Determinants, Numerical Integration, Binary Trees, Matrix Eigenvalues a) Implement the computation of determinants using Laplace expansion by minors [1192], and using this
implementation, find the determinant of Array[Which[#2 - 2 {bigIntegerSay1000}]; without using ContourPlot (and without reprogramming ContourPlot) by solving differential equations for the nodal curve(s). (The function to be visualized is an eigenfunction of the Helmholtz operator on the square; in comparison to most examples treated in Solution 3 of Chapter 3 of the Graphics volume [1794], this times the weights of the two eigenfunctions (with the same eigenvalue) are slightly different, and, as a result, self-intersections of the nodal curve become atypical in this case; see [437], [1250], and [768].) a) Consider the nonlinear Bloch equations [1834]
Sx£ HtL = k S y HtL Sz HtL S £y HtL = Sz HtL + k Sx HtL Sz HtL Sz£ HtL = -S y HtL. Show how the solution curves 8Sx HtL, S y HtL, Sz HtL< depend on k. Choose random initial conditions on the unit sphere Sx H0L2 + S y H0L2 + Sz H0L2 = 1. 17.L1 Branch Cuts of an Elliptic Curve, Strange 4D Attractors a) Make a picture of the branch cuts of the function
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 4 2 1 2ip j 1 2ip j ip 3 2ip j ip ( z  Jz - ÅÅÅÅÅÅ e ÅÅÅÅÅÅÅÅ7ÅÅÅÅÅÅÅ N  Jz - ÅÅÅÅÅÅ e ÅÅÅÅÅÅÅÅ5ÅÅÅÅÅÅÅ + ÅÅÅÅ10ÅÅÅ N  Jz - ÅÅÅÅÅÅ e ÅÅÅÅÅÅÅÅ3ÅÅÅÅÅÅÅ + ÅÅÅÅ6ÅÅÅ N . 4 2 4 j=0
j=0
j=0
First, solve it by using ContourPlot. Second, solve a differential equation for the location of the branch cut and then display the result of solving the differential equation. b) Find systems of coupled nonlinear ODEs of first order x£i HtL = pi Hx1 HtL, x2 HtL, x3 HtL, x4 HtLL, i = 1, 2, 3, 4 whose solutions exhibit strange attractors in 4D. Use low-order polynomials for the pi .
18.L1 Differently Colored Spikes, Billiard with Gravity a) Color the various spikes in the following picture differently.
f[ϕ_, ϑ_] := Function[r, (Sign[#] Abs[#]^(5/3))& /@ N[r {Cos[ϕ] Sin[ϑ], Sin[ϕ] Sin[ϑ], Cos[ϑ]}]][N @ Abs[(3465/16(1 - Cos[ϑ]^2)^(3/2)*(221Cos[ϑ]^6 195Cos[ϑ]^4 + 39Cos[ϑ]^2 - 1)) Cos[4ϕ]]] ParametricPlot3D[f[ϕ, ϑ], {ϕ, 0, 2Pi}, {ϑ, 0, Pi}, PlotPoints -> {41, 41}, Compiled -> False,
Numerical Computations
536 PlotRange -> All, BoxRatios -> {1, 1, 1}, Boxed -> False, Axes -> False];
b) Consider a point particle in 2D under the influence of gravity (acting downward) being repeatedly and ideally
reflected from the curve ¶
1 1 1 yHxL = - „ qJx - k + ÅÅÅÅÅ N qJk + ÅÅÅÅÅÅ - xN H-1Lk $%%%%%%%%%%%%%%%%%%%%%%%%%%%% ÅÅÅÅÅÅ - Hx - kL2% . 2 2 4 k=-¶
Visualize some qualitatively different trajectories for various initial conditions. 19.L2 Schwarz–Riemann Minimal Surface, Jorge–Meeks Trinoid, Random Minimal Surfaces a) Make a picture of the following Schwarz–Riemann minimal surface [1351], [1626], [616], [617], and [1303]
(see also Subsection 1.5.2 of the Symbolics volume [1795]): 1 i s+i t y 8xHs, tL, yHs, tL, zHs, tL< = Rejjj‡ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 81 - w2 , iH1 + w2 L, 2 w2 < dwzzz. è!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1 - 14 w4 + w8 k 0 { The parameters s and t are from the region of the s,t-plane where the following four circles overlap: 2 2 Hs ≤ 2-1ê2 L + Ht ≤ 2-1ê2 L = 2. Carry out all calculations numerically. The resulting surface can be smoothly continued by reflecting the surface across the lines that form its boundary. Carry out this continuation. b) Make a picture of the following minimal surface (Jorge–Meeks trinoid) [132], [1555], [1171] and [1369] (see
also Subsection 1.5.2 of the Symbolics volume [1795]): 1 i s+i t y 8xHs, tL, yHs, tL, zHs, tL< = Rejj‡ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ2Å 81 - w4 , iH1 + w4 L, w2 < dwzz. k 0 { Hw3 - 1L w = s + i t, s, t œ . Carry out all calculations numerically. The Jorge-Meeks trinoid has a threefold rotational symmetry and four-mirror symmetry plane. Make use of this symmetry in the construction. A region in the s,t-plane that generates one part of the surface is in polar coordinates given by 0 § r < 1, 0 § j § p ê 3. c) For the following pairs of functions f HxL and gHxL, calculate numerically the parts of the surfaces (for some suitable r0 ) that are defined via
i r expHi jL y 8xHr, jL, yHr, jL, zHr, jL< = Rejj‡ 8H1 - gHxL2 L, iH1 + gHxL2 L f HxL, 2 f HxL gHxL< dxzz. k r0 { If the functions f HxL and gHxL have branch cuts, continue the functions to the next Riemann sheet to avoid discontinuities. This is the list of function pairs: 67 f HxL = x - ÅÅÅÅÅÅ ÅÅ 78 14 1 f HxL = x + ÅÅÅÅÅÅÅÅÅ + ÅÅÅÅÅ2ÅÅÅ 27 x
2 44 1 gHxL = J ÅÅÅÅÅ - 1N + x2 + 2 x + ÅÅÅÅÅÅÅÅÅ 31 x 1 gHxL = ÅÅÅÅÅÅÅÅ ÅÅÅÅÅ x5ê3
Exercises
537 2 1 2 112 f HxL = x3 + 2 x + ij ÅÅÅÅÅÅÅÅ ÅÅÅÅÅ - 1yz + ÅÅÅÅÅ gHxL = 2 x + ÅÅÅÅÅÅÅÅÅÅÅÅÅ 4ê3 3 69 kx { 2
1 ÅÅÅÅÅÅ - 1M Hx - 2L I ÅÅÅÅ x 5ê3 ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ - 2 gHxL = ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ x3
f HxL = -2 x4 1173 f HxL = - ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ x-3 310 1 2 f HxL = J2 + ÅÅÅÅÅ6Å Å N x
gHxL = x3 28 2 gHxL = - ÅÅÅÅÅÅ ÅÅ x Hx5ê3 + 1L 55
28 3 x + ÅÅÅÅÅÅÅÅÅ + 2 f HxL = $%%%%%%%%%%%%%%%%% 9
1 y gHxL = sinhij ÅÅÅÅÅÅÅÅ ÅÅ Å z k x4ê3 {
7 x - ÅÅÅÅ ÅÅ 12 ÅÅÅÅÅÅ f HxL = ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 3 x lnH2L f HxL = - ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅ 1 lnI ÅÅÅÅÅÅÅÅ ÅÅ Å M x 2 +1
61 gHxL = ÅÅÅÅÅÅÅÅÅ x7ê3 56 20 gHxL = - ÅÅÅÅÅÅÅÅÅÅÅÅÅÅ2ÅÅ 17 x
ip f HxL = ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅ 5ê3 lnHHx + 1L-2 L
4 ÅÅÅÅx2ÅÅÅ -1 gHxL = J2 x + ÅÅÅÅÅÅ N 5
32
1
-2
yz ij ln ÅÅÅÅ9ÅÅÅ HxL f HxL = jjjj ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ + 1zzz 3000000 { k
x3 gHxL = ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ2ÅÅ . 1 I ÅÅÅÅÅÅÅÅ ÅÅÅÅÅ - 1M 4 x 4ê3
20.L2 Precision Modeling, GoldenRatio Code from the Tour, Resistor Network a) Model the following curve (as a function[al] of f[x]):
f[x_] := 2 - x - 5x^2 + 4x^3 + 3x^4 - 2x^5; SetPrecision[Round, False]; ListPlot[Table[{x, Precision[f[SetPrecision[x, 25]]]}, {x, -5, 5, 10/1001}], PlotRange -> {{-5, 5}, {20, 30}}, Frame -> True, PlotJoined -> True, Axes -> False]; b) Why do the following two definitions below from page 18 of The Mathematica Book [1919] really work and
give as a result the value of GoldenRatio to k digits? Should not there be a small loss of precision in every step of the FixedPoint calculation? g1[k_] := FixedPoint[N[Sqrt[1 + #], k]&, 1] g2[k_] := 1 + FixedPoint[N[1/(1 + #), k]&, 1] c) Predict the first few digits of the number calculated by the following sequence of inputs.
data = Table[If[Not[IntegerQ[n/10]], {n, Coefficient[Fit[Table[Plus @@ IntegerDigits[n^k], {k, 100}], {1, x}, x], x]}, Sequence @@ {}], {n, 1000}]; fit = Fit[data, {Log[10, n]}, n]
Numerical Computations
538
d) The resistance Rm,n between the lattice point 80, 0< and the lattice point 8m, n< of an infinite square lattice
with unit resistors between lattice points obeys the following set of equations for nonnegative n, m [443], [444], [445], [1840]: m+1 2m+1 Rm+2,m+2 = 4 ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ Rm+1,m+1 - ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ Rm,m 2m+3 2m+3 Rn+2,n+1 = 2 Rn+1,n+1 - Rn+1,n Rm+2,0 = -Rm,0 + 4 Rm+1,0 - 2 Rm+1,1 Rm+1,n = -Rm,n - Rm+1,n-1 - Rm+1,n+1 + 4 Rm+1,n if 2 < n < m + 1 Rn,m = Rm,n The initial conditions for the recursion are R0,0 = 0, R1,0 = 1 ê 2, and R1,1 = 2 ê p. Visualize Rn,m for 0 § n, m § 200. In which direction is the resistance (for a fixed distance) the largest? For large distances, the following asymptotic expansion holds: 1 logH8L è!!!!!!!!!!!!!!!!!! Rn,m øøøøøøøøø ö! ÅÅÅÅÅÅ JlogI m2 + n2 M + g + ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ N. è!!!!!!!!!!!!!!!!!!!!!!!!!! 2 n2 +m2 ض p In which direction does this expansion hold best? 21.L3 Auto-Compiling Functions, Card Game a) Given some function definitions for a symbol f (such as f[x_, y_] :=…, f[x_, y_, z_] :=…), implement a function to be called on f such that subsequent calls to f with specific numeric arguments generate and use compiled versions of the appropriate definitions. Calls to f with uncompilable arguments should use the original definitions for f. b) Consider the following card game [175]: Two players each get n cards with unique values between 1 and 2 n. In each round, each player selects one card randomly from their pile. The player with the smaller card value wins both cards. The game ends when one player runs out of cards.
If possible, speed up the following implementation of the modeled game (A and B are the two initial lists of card values). cardGameSteps1 = Compile[{{A, _Integer, 1}, {B, _Integer, 1}}, Module[{a = A, b = B, ra, rb, (* round counter *) = 0}, While[a != {} && b != {}, ++; (* select two random cards *) ra = Random[Integer, {1, Length[a]}]; rb = Random[Integer, {1, Length[b]}]; (* compare cards and add new card to one player; remove second card from other player *) If[a[[ra]] > b[[rb]], b = Append[b, a[[ra]]]; a[[ra]] = a[[-1]]; a = Drop[a, -1], a = Append[a, b[[rb]]]; b[[rb]] = b[[-1]]; b = Drop[b, -1]]]; (* return number of rounds *) ]]; For n = 10 carry out 106 games and calculate the average length of the game.
Exercises
539
22.L2 Path of Steepest Descent, Arclength of Fourier Sum, Minimum-Energy Charge Configuration a) For the spiral minimum search problem from Section 1.9, find the minimum by following the path of steepest
descent until one reaches the minimum. n b) Consider the partial sums ⁄k=1 sinHk xL ê k of the Fourier series of the function f HxL = p ê 2 - x ê 2. As n Ø ¶,
the arclength of the graph of the Fourier series diverges [1723], [1482]. How many terms does one have to take into account so that the arclength of the graph of the Fourier series is equal to or greater than twice the arclength of f HxL? c) Consider 48 n (n = 1, 2, …) point charges on a sphere. Enforce the symmetry group of the cube (that has 48 elements) on the charges and find minimum energy configurations for the charge positions for small n. Compare results and timings for various method option settings. Calculate the minimum energy configuration for n = 36.
23.L2 N[expr, prec] Questions and Compile Questions a) Might it happen that N[expr, prec] (prec < ¶) returns a result with infinite precision for a NumericQ expr? b) Predict the result of the following input.
Precision[SetAccuracy[10^+30 Accuracy[SetPrecision[10^+30 Precision[SetAccuracy[10^-30 Accuracy[SetPrecision[10^-30
Pi, Pi, Pi, Pi,
50]] 50]] + 50]] 50]]
c) Predict the result of the following input.
Log[10, Abs[N[SetPrecision[SetPrecision[Pi, 50], Infinity]/Pi - 1, 30]]] < -50 d) Construct two functions built from elementary functions (like Log, Exp, Sqrt, Power, Sin, Cos, …) f1 HxL
and f2 HxL, such that the precision f1 HxL is more than ten times the precision of the argument x, such that the precision of f2 HxL is less than one-tenth of the precision of the argument x. e) For a numerical expression expr, N[expr, prec] (with prec > $MachinePrecision) typically gives a result that is correct to precision prec. Try to construct an expression expr such that: † returns true for NumericQ[expr] † is built from elementary functions (like Log, Exp, Sqrt, Power, Sin, Cos, …) † is not identically zero † does not give any N::meprec messages when N[expr, 50] is evaluated † gives a result for N[expr, 50] that is wrong in the first digit already. (Do not use Unprotect, or set unusual UpValues, ….) f) Typically, doing a calculation with machine numbers is faster than doing a calculation with high-precision
numbers. Find a counter example to this statement. g) Find a symbolic numeric expression expr (meaning NumericQ[expr] yields True and Precision[expr]
gives Infinity), that contains only analytic functions and that, when evaluated, gives N::meprec or Divide::infy messages. h) Why do the following two inputs give different results?
Compile[{x}, 2/Exp[x]][1000] Compile[{x}, Evaluate[2/Exp[x]]][1000]
540
Numerical Computations
i) Explain the look of the following three plots.
Plot[FractionalPart[Exp[n]],{n, 0, 200}, Frame -> True, Axes -> False, PlotRange -> All]; f[n_?NumberQ] := FractionalPart[Exp[SetPrecision[n, Infinity]]]; Plot[f[n], {n, 0, 200}, Frame -> True, Axes -> False, PlotRange -> All]; $MaxExtraPrecision = 1000; Plot[f[n], {n, 0, 2000}, Frame -> True, Axes -> False, PlotRange -> All]; j) For most inputs input, the compiled version Compile[{}, input][] will give the same result as the uncompiled one. Find an example where the compiled version gives a different result. k) Predict the result of the following input.
Round[E - w[1] /. NDSolve[{w'[z] == (x /. FindRoot[ (y /. FindMinimum[-Cos[y - x], {y, x + Pi/8}][[2]]) == w[z], {x, 0, 1}]), w[0] == 1}, w, {z, 0, 1}][[1]]] Avoid the premature evaluation of the arguments of the numerical functions. l) Find three real numbers a, b, and c such that three expressions a === b, a === c, and b === c all give True, but Union[{a, b, c}] returns {a, b, c}. m) Predict the result of the following input.
Precision[Im[SetPrecision[N[#, 200]& /@ Unevaluated[10^100 + 10^-10 I], 200]]] n) Find an algebraic expression (containing arithmetic operations and one-digit integers) x that is zero such that N[x] gives a result value whose magnitude is larger than 1. o) Predict the result of the following input.
Compile[{{Pi, _Real}}, Pi][2] p) Will evaluating the following input give True?
N[FindRoot[1]] - (FindRoot[N[1]]) === 0 q) Given the following definition for the function f, find an argument x, such that evaluating f[x] emits a N::meprec message when evaluating the right-hand side of the function definition. f[x_Real] := N[x, $MachinePrecision] r) Find an (analytic in the function-theoretic sense) integrand intHxL, such that NIntegrate[intHxL, {x, 0,
Infinity}] does not issue any messages and returns a result that is twice the correct value. s) Devise exact rational numbers xk , such that the expression N[1, 20] + N[x1 , 20] + ∫ + N[xn , 20] == N[1 + x1 + … + xn , 20] would evaluate to False. (Assume that $MachinePrecision is less than 20.) t) Guess the shape of the graphic produced by the following input. What exactly does the input do?
squareRootOf3CF = With[{p = $MachinePrecision - 2}, With[{ = (# (1 + Random[Real, {-1., 1.} 10.^-p]))&}, Compile[x, FixedPoint[
Exercises
541 Function[ξ, [[[ξ]/[2.]] + [[3.]/[2.]/[ξ]]]], x]]]];
roots = Table[squareRootOf3CF[1.], {10^5}] Show[Graphics[ Polygon[{{#1 - 1/2, 0}, {#1 + 1/2, 0}, {#1 + 1/2, #2}, {#1 - 1/2, #2}}]&[First[#], Length[#]]& /@ Split[Round[(Sqrt[3] - Sort[roots])* 10^($MachinePrecision - 3/2)]]], Frame -> True]; u) Implement an optimized version of the following function f. Visualize f[1/GoldenRatio, 10^5, 10^5], f[1/Pi, 10^5, 10^5], and f[1/E, 10^5, 10^5].
f[x_?(0 < # < 1&), p_Integer, n_Integer] := MapIndexed[#1^(1/#2[[1]])&, Rest[ FoldList[Times, 1, Rest[First /@ Rest[ NestList[{FromDigits[{Last[#], 0}, 2.], Drop[Last[#], Position[Last[#], 1, {1}, 1][[1, 1]]]}&, {1, RealDigits[x, 2, p][[1]]}, n]]]]]]; v) Find two approximative numbers z1 and z2 and a numerical function f , such that z1 ===z2 returns True, but
f Hz1 L=== f Hz2 L returns False. Can one find examples for high-precision numbers z1 and z2 and a function f continuous in the neighborhood of z1 , z2 ? w) Find a short (shorter than 20 characters) input that issues a N::meprec message. x) As mentioned in the main text, linear algebra functions operating on high-precision matrices use internally
fixed-precision to carry out the calculations to avoid excessive cancellations. As a result of using fixed-precision arithmetic, the resulting digits of all numbers are no longer guaranteed to be correct. Find an example of a 3 μ 3 high-precision matrix, where Inverse applied to this matrix results in matrix elements with incorrect digits. y) Predict the result of the following input.
(ArcTan[10^100] - Pi/2)^0``100 z) Predict the result of the following input:
f[x_] := x/Sqrt[x^2] Exp[-1/Sqrt[x^2]] f[x /; x == 0] = 0 FindRoot[f[x/10] == 0, {x, 1}] How does one set the options of FindRoot to get the zero x0 = 0 of f[x/10] within †x0 § < 10-6 ? a) Why does the following input give a message?
Module[{c = 0.5436268955915372089486, g}, g[x_] := x + c; NIntegrate[g[x] - 1/g[x], {x, 0, 1}]] 24.L2 Series Expansion for Anharmonic Oscillator a) After making the substitution yHxL = expH-x3 ê 3L uHxL [688], [58], [773], [701] for yHxL in
- y≥ HxL + x4 yHxL = l yHxL
Numerical Computations
542
i we get a new differential equation for uHxL. Making for uHxL a power series ansatz of the form uHxL = ⁄¶ i=0 ai x i calculate the first 100 ai . Determine l such that the first zero in x of expH-x3 ê 3L ⁄100 a x is a double zero. i=0 i
b) After making the substitution yHxL = expH-x2 ê 2L uHxL for yHxL in
- y≥ HxL + Hx2 + x4 L yHxL = l yHxL we get a new differential equation for uHxL [1809], [1810]. Making for uHxL a power series ansatz of the form i uHxL = ⁄¶ i=0 ai HlL x calculate the first 200 ai . Determine l such that the first zero in l of ai HlL. How many correct digits does one get from a200 ? yn HxL = ⁄ni=0 ai HlL xi of the differential equation - y HxL + x yHxL = l yHxL, yH≤¶L = 0. Determine the upper and lower bounds for the lowest possible l by finding high-precision approximations for the zeros of yn Hx* L and y£n Hx* L for “suitably chosen” x* . Find an approximation for the lowest possible l that is correct to 1000 digits [1796]. c) Generate n terms of the power series solution ≥
4
25.L1 Gibbs Distributions, Optimal Bin Size, Rounded Sums, Odlyzko-Stanley Sequences a) Model the approach to equilibrium of an ensemble of pairwise interacting particles. Let a set of n particles,
each initially having energy e0 , be given. For all particles, allow only (positive) integer-valued energies. Model a two-body collision by taking two randomly selected particles and randomly redistribute their (common) energy between these two particles [592], [516], [365]. b) In [595], [596], the following statistical mechanics-inspired method for the generation of n normally distributed random numbers was given: Prepare a list of n approximative 1’s. Randomly (with uniform probability distribution) select two nonidentical integers i and j. Update the ith and jth elements li and l j according to è!!!! è!!!! li£ = Hli + l j L ë 2 , l£j = H2 2 l j - l j - l j L ë 2 . Here is a random variable with values ≤1. Repeat this updating process about 3 ê 2 logHnL n times. Then, one obtains n normally distributed random numbers with probability distribution pHxL = H2 pL-1ê2 expH-x2 ê 2L.
Implement a compiled version of this method for generating normally distributed random numbers. Compare the resulting distribution with the ideal one. How long does it take to generate 106 numbers in this way? Compare with the direct method that uses the inverse error function InverseErf. c) Generate 104 sums of 103 uniformly distributed numbers. Use the central limit theorem to approximate the
distribution function of the sums. Which bin size results in a minimal mean square difference between an approximative histogram density and the limit distribution? d) Typically, the sum of rounded summands does not coincide with the rounded sum of summands. Let xk be uniformly distributed random variables from @-L, LD and zk their rounded nearest integers in base b (assume n n L ¥ 1 ê b). Then the probability pHbL n that the two sums ⁄k=1 xk and ⁄k=1 zk rounded to the nearest multiple of b coincide is [1175] ¶ 2 sinHxL n-1 sin2 Hb xL pHbL J ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ N ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ ÅÅÅÅÅÅÅÅÅÅÅ H1 + dn mod 2,0 cosHxLL dx. n = ÅÅÅÅÅÅÅÅÅÅ ‡ x pb 0 x2
Form a random sum with n = 106 terms that confirms this probability for b = 10 within 10-5 . e) Implement a function that returns all elements of the Odlyzko-Stanley sequence k that are less than a given integer n. The Odlyzko-Stanley sequence k is the sequence of integers 8a0 , a1 , …, a j , …< with a0 = 0, a1 = k, and a j defined implicitly through the condition that it is the smallest integer, such that the sequence 8a0 , a1 , …, a j-1 < does not contain any subsequence of three elements that form an arithmetic progression [677]. Visualize the resulting sequences and local averages of the sequences for k = 1, …, 13 and n = 106 .
Exercises
543
26.L1 Nesting Tan, Thompson’s Lamp, Digit Jumping a) Explain the “steps” visible in the following picture.
nl = NestList[Tan, N[2, 200], 2000]; precList = Precision /@ nl; ListPlot[precList]; b) Explain some characteristics of the following graphic.
fl = Rest[FoldList[Times, 1., Table[Tan[k], {k, 2 10^5}] // N]]; ListPlot[Log @ Abs[fl], PlotRange -> All, PlotStyle -> {PointSize[0.002]}] c) Predict whether in the following attempt to model Thompson’s lamp [1762], [167], [190], [775], [744], [529], [457], [1737], [1456], [1644], [430] the lamp be on or off “at the end”? Do not run the code to find out.
t = 0; δt = 1/2; lampOnQ = True; While[t != 1``10000, t = t + δt; δt = δt/2; lampOnQ = Not[lampOnQ]] lampOnQ What happens when one replaces 1``10000 by the exact integer 1? d) What does the following code do and what is the expected shape of the resulting plots?
cf = Compile[{{n, _Integer}}, Table[Module[{digits, λ = 100, k = 1, sOld = 1, sNew = 1}, digits = Join[{Random[Integer, {1, 9}]}, Table[Random[Integer, {0, 9}], {λ}]]; While[k++; If[sOld > λ, digits = Join[digits, Table[Random[Integer, {0, 9}], {sOld}]]; λ = Length[digits]]; sNew = sOld + digits[[sOld]]; sOld =!= sNew, sOld = sNew]; {k, sNew}], {n}]]; data = cf[10^6]; Show[GraphicsArray[ ListPlot[{First[#], Log @ Length[#]}& /@ Split[Sort[# /@ data]], PlotRange -> All, DisplayFunction -> Identity]& /@ {First, Last}]]; 27.L2 Parking Cars, Causal Network, Seceder Model, Run Lengths, Cycles in Random Permutations, Iterated Inner Points, Exchange Shuffling, Frog Model, Second Arcsine Law, Average Brownian Excursion Shape a) Make a Monte-Carlo simulation of the following problem: Cars of length 1 are parked randomly inside a
linear parking lot of length l (consider the cases l = 100, l = 1000). What is the expected number of cars that fit into the lot? Compare with the theoretical result [1005], [1426], [1466] for large l 1 expectedNumberOfCars = c l - H1 - cL + OJ ÅÅÅÅÅÅ N l where c is given by
Numerical Computations
544
¶
t 1 - e-u i y c = ‡ expjj-2 ‡ ÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅÅ duzz dt. u k { 0 0
Write a version of the simulation that makes use of Compile. b) Find a fast method to calculate the ym n (-1000 § m § m, 0 § n § 1000) that obey the following equations [899]: m+1 m-1 m ym yn yn+1 = 1 n yn m y0 = 1 - 2 dm,0 ym 1 = 1.
0 § n < ¶, -¶ < m < ¶
c) The seceder model [509], [1693] (used to model the spontaneous formation of groups) is the following:
Starting with a list l of n zeros, one step consists of n iterations of an update step. In the update step, randomly three elements of l are selected. Then the element of the three that has the largest distance from the average is chosen. A random real number (say uniformly distributed in @-1, 1D) is added the selected element and the resulting value replaces a randomly chosen element of l. All other elements of l stay unchanged. Implement the seceder model efficiently. Run and visualize 1000 update steps of a starting list of length 1000. Is a run and a visualization of 10000 update steps of a starting list of length 10000 doable? d) A run in a list of numbers 8n1 , n2 , …, nk < is a sublist of consecutive increasing numbers 8ni , ni+1 , …, ni+l