August 28, 2010

Minh Van Nguyen

Ethics in open source software

This is a slightly edited version of my posting to the group sage-devel. It raises some issues concerning ethics in open source software. An excellent overview can be found in the paper (Grodzinsky et al. 2003) [1]. My response follows, with any email addresses removed. Hi Mike, On Mon, Aug 23, 2010 at 1:07 AM, [...]

by mvngu at August 28, 2010 09:31 PM

August 21, 2010

Christopher Olah

3D printing of Mathematical Objects!

Back in the fall I did some work on getting hacklab.to‘s 3d-printer to print mathematical objects created in sage. Unfortunately, shortly after I got it to work and printed a test sphere, the 3d printer broke. Thus began a long succession of the makerbot — nicknamed the break-r-bot — being fixed and broken… spending most [...]

by christopherolah at August 21, 2010 04:36 AM

August 19, 2010

Martin Albrecht

Somewhat Homomorphic Encryption

Today I read the paper “Computing Arbitrary Functions of Encrypted Data” by Craig Gentry in which he explains the basic ideas behind his work on fully homomorphic encryption. If you don’t know what homomorphic encryption is: it means that one … Continue reading

by martinralbrecht at August 19, 2010 05:59 PM

August 18, 2010

William Stein

*-Overflow

I spent some time obsessively browsing http://mathoverflow.net during the last few days (and posting too), and it is a really awesome site.  I found out about it last December, when I visited Berkeley to give a talk, and had lunch with one of the guys that runs the site, but didn't pay much attention to it until recently.  It's much more suitable for discussion of research-level mathematics than general use and development of Sage.

Mathoverflow is interesting in that their comment system supports jsmath with realtime preview, which is something the TinyMCE editor in the Sage notebook doesn't do. It's also something that http://stackoverflow.com doesn't do, as far as I can tell. The  grad students at Berkeley that organize mathoverflow probably somehow hacked jsmath into the comment system.

I was very surprised to learn that Mathoverflow and Stackoverflow (and all the dozens and dozens of stackoverflow-based sites) are closed source. There is a company that runs stackoverflow and hosts related sites, and keeping their code closed is part of their business model.

Some people sort of forked something related to stackexchange at some point, and created this: CNPROG, which is fortunately based on Python.  There are about 20 sites using CNPROG now, including one for all questions about the use of Python in science, mathematics, and engineering.
I tried this site, answering a question about Cython, and it is snappy and clean.

Perhaps I will add jsmath or mathjax support to cnprog and start another site (http://q.sagemath.org ?), say on using math software as an aid to mathematical research. The site would not be specific to Sage or restricted to open source. The FAQ would say that all questions must be of the form: "(How) can I use a computer to compute XYZ, where XYZ should be some sort of advanced mathematical question." The emphasis on "advanced" and "research" is that there are already other sites about how to do elementary stuff (=people's homework), and it will provide an excuse to keep that out, which will greatly raise the quality.   It is, after all, exactly this uncompromising focus on research that makes http://mathoverflow.net so interesting.

EDIT: I've now created http://ask.sagemath.org which is based on http://askbot.org, which is in turn based on CNPROG. 

by William Stein (wstein@gmail.com) at August 18, 2010 04:29 PM

August 17, 2010

Alasdair McAndrew

The NSH method for matrix inversion

We all know that systems of linear equations can be solved iteratively, using either the Jacobi or Gauss-Seidel methods. But I’ve just learned there’s a neat method for computing matrix inverses iteratively. Of course, in practice matrix inverses aren’t hugely used (except perhaps in computer graphics), but the concept of the matrix inverse is certainly [...]

by amca01 at August 17, 2010 11:28 PM

August 12, 2010

Doxdrum

Graphics Array in Sage(math)

For a publication I was working on, I plotted functions in  PDF format. However, the journal ask me to handle them in EPS format. “What’s the point?” you might ask. Well, since I installed Lucid Lynx (a clean installation), the files of those graphic were gone… Fool of me, you will say, but really, I [...]

by doxdrum at August 12, 2010 12:23 PM

August 04, 2010

Fredrik Johansson

Euler-Maclaurin summation of hypergeometric series

I recently fixed another corner case (it's always the corner cases that are hard!) in the hypergeometric function evaluation code in mpmath.

The difficulty in question concerns the functions pFp-1(...; ...; z), of which the Gauss hypergeometric function 2F1 is an important special case. These functions can be thought of as generalizations of the geometric series



and the natural logarithm



and share the property that the hypergeometric (Maclaurin) series has radius of convergence 1, with a singularity (either algebraic or logarithmic, as above) at z = 1.

Numerical evaluation is fairly easy for z in most of the complex plane. The series for pFp-1(...; ...; z) converges like the geometric series, so direct summation works well for, say, |z| ≤ r 0.9. Likewise, there is an analytic continuation formula which transforms z to 1/z, allowing evaluation for (say) |z| ≥ 1.1.

The remaining shell around the unit circle 0.9 |z| 1.1 is the difficult region. In fact, 2F1 can still (essentially) be computed using exact transformations here, but the higher cases remain difficult. As mentioned in an earlier post, mpmath handles this by calling nsum() which applies convergence acceleration to the slowly converging series. In particular, nsum implements the (generalized) Shanks transformation which is extremely efficient for this particular type of series – in fact, it works outside the radius of convergence (Shanks transformation effectively computes a Padé approximant), so it can be used anywhere in the difficult shell.

Still, the Shanks transformation is most efficient when arg(z) = ±π and unfortunately degenerates as arg(z) → 0, i.e. close to z = 1. nsum also implements Richardson extrapolation, which sometimes works at z = 1, but only for special parameter combinations in the hypergeometric series (although those special combinations happen to be quite important – they include the case where the hypergeometric series reduces to a polygamma function or polylogarithm).

Thus, we have the following evaluation strategy for pFp-1:

Blue: direct summation (with respect to z or 1/z)
Yellow: Shanks transformation
Red: ???



A commenter suggested trying some other convergence acceleration techniques (like the Levin transformation). But it seems that they still will fail in some cases.

Thus I've finally implemented the Euler-Maclaurin summation formula for the remaining case. The E-M formula differs from other convergence acceleration techniques in that it is based on analyticity of the integrand and does not require a particular rate of convergence. It is implemented in mpmath as sumem(), but requires a little work to apply efficiently.

To apply the E-M formula to a hypergeometric series Σ T(k), the term T(k) must first of all obviously be extended to an analytic function of k, which is done the straightforward way by considering the rising factorials as quotients of gamma functions a(a+1)...(a+k−1) = Γ(a+k) / Γ(a).

We are left with the difficulty of having to integrate T(k) and also to compute n-th order derivatives of this function for the tail expansion in the E-M formula (neither of which can be done in closed form). Fortunately, numerical integration with quad() works very well, but the derivatives remain a problem.

By default, sumem() computes the derivatives using finite differences. Although this works, it gets extremely expensive at high precision for hypergeometric series due to the rapidly increasing cost of evaluating the gamma function as the precision increases. But T(k) is a product of functions that individually can be differentiated logarithmically in closed form (in terms of polygamma functions). I therefore implemented the equivalent of symbolic high-order differentiation for products and the exponential function using generators.

diffs_prod generates the high-order derivatives of a product, given generators for products of individual factors:

>>> f = lambda x: exp(x)*cos(x)*sin(x)
>>> u = diffs(f, 1)
>>> v = diffs_prod([diffs(exp,1), diffs(cos,1), diffs(sin,1)])
>>> next(u); next(v)
1.23586333600241
1.23586333600241
>>> next(u); next(v)
0.104658952245596
0.104658952245596
>>> next(u); next(v)
-5.96999877552086
-5.96999877552086
>>> next(u); next(v)
-12.4632923122697
-12.4632923122697


diffs_exp generates the high-order derivatives of exp(f(x)), given a generator for the derivatives of f(x):

>>> def diffs_loggamma(x):
... yield loggamma(x)
... i = 0
... while 1:
... yield psi(i,x)
... i += 1
...
>>> u = diffs_exp(diffs_loggamma(3))
>>> v = diffs(gamma, 3)
>>> next(u); next(v)
2.0
2.0
>>> next(u); next(v)
1.84556867019693
1.84556867019693
>>> next(u); next(v)
2.49292999190269
2.49292999190269
>>> next(u); next(v)
3.44996501352367
3.44996501352367


Actually only differentiation of the exponential function is necessary, which I didn't realize at first, but the product differentiation is still a nice feature to have.

Exponential differentiation amounts to constructing a polynomial of n+1 variables (the derivatives of f), which has P(n) (partition function) ≈ exp(√n) terms. Despite the rapid growth, it is indeed faster to use this approach to differentiate gamma function products at high precision, since the precision can be kept constant. In fact, this should even work in double precision (fp arithmetic) although I think it's broken right now due to some minor bug.

As a result of all this, here are two examples that now work (the results have full accuracy):


>>> mp.dps = 25
>>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','41/8'], 1)
2.219433352235586121250027

>>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], 1)
+inf
>>> eps1 = extradps(6)(lambda: 1 - mpf('1e-6'))()
>>> hyper(['1/3',1,'3/2',2], ['1/5','11/6','5/4'], eps1)
2923978034.412973409330956


Application: roots of polynomials



A neat application is to compute the roots of quintic polynomials. Such roots can be expressed in closed form using hypergeometric functions, as outlined in the Wikipedia article Bring radical. This is more interesting in theory than practice, since polynomial roots can be calculated very efficiently using iterative methods.

In particular, the roots of x5 - x + t are given (in some order) by



where



Just verifying one case:


>>> mp.dps = 25; mp.pretty = True
>>> t = mpf(3)
>>> for r in polyroots([1,0,0,0,-1,t]):
... print r
...
-1.341293531690699250693537
(0.9790618691253385511579325 - 0.6252190807348055061205923j)
(0.9790618691253385511579325 + 0.6252190807348055061205923j)
(-0.3084151032799889258111639 + 1.249926913731033699905407j)
(-0.3084151032799889258111639 - 1.249926913731033699905407j)
>>> -t*hyper(['1/5','2/5','3/5','4/5'], ['1/2','3/4','5/4'], 3125*t**4/256)
(-0.9790618691253385511579325 + 0.6252190807348055061205923j)


Now, we can choose t such that the hypergeometric argument becomes unity:


>>> t = root(mpf(256)/3125,4)
>>> for r in polyroots([1,0,0,0,-1,t]):
... print r
...
-1.103842268886161371052433
(0.6687403049764220240032331 + 3.167963942396665205386494e-14j)
(0.6687403049764220240032331 - 3.172324181973539074536523e-14j)
(-0.1168191705333413384770166 + 1.034453571405662514459057j)
(-0.1168191705333413384770166 - 1.034453571405662514459057j)

>>> -t*hyper(['1/5','2/5','3/5','4/5'], ['1/2','3/4','5/4'], 1)
-0.6687403049764220240032331


The last line would previously fail.

Interesting to note is that the value at the singular point z = 1 corresponds to a double root. This also makes polyroots return inaccurate values (note the imaginary parts), a known deficiency that should be fixed...

Better methods



In fact, there may be better methods than the Euler-Maclaurin formula. One such approach is to use the Abel-Plana formula, which I've also recently implemented as sumap(). The Abel-Plana formula gives the exact value for an infinite series (subject to some special growth conditions on the analytically extended summand) as a sum of two integrals.

The Abel-Plana formula is particularly useful when the summand decreases like a power of k; for example when the sum is a pure zeta function:


>>> sumap(lambda k: 1/k**2.5, [1,inf])
1.34148725725091717975677
>>> zeta(2.5)
1.34148725725091717975677

>>> sumap(lambda k: 1/(k+1j)**(2.5+2.5j), [1,inf])
(-3.385361068546473342286084 - 0.7432082105196321803869551j)
>>> zeta(2.5+2.5j, 1+1j)
(-3.385361068546473342286084 - 0.7432082105196321803869551j)


It actually works very well for the generalized hypergeometric series at the z = 1 singularity (which, as mentioned earlier, is a generalized polygamma function, polylogarithm, or zeta function of integer argument), and near the singularity as well. It should even be slightly faster than the Euler-Maclaurin formula since no derivatives are required. Yet another possibility is to integrate a Mellin-Barnes type contour for the hypergeometric function directly.

But at present, I don't want to modify the existing hypergeometric code because it works and would only get more complicated. Rather, I want to improve nsum so it can handle all of this more easily without external hacks. The numerical integration code should also be improved first, because there are still certain parameter combinations where the hypergeometric function evaluation fails due to slow convergence in the numerical integration (this is due to an implementation issue and not an inherent limitation of the integration algorithm).

by Fredrik Johansson (fredrik.johansson@gmail.com) at August 04, 2010 04:27 PM

July 27, 2010

Fredrik Johansson

Post Sage Days 24 report

Now that I've overcome the immediate effects of SDWS (Sage Days Withdrawal Syndrome), I should write a brief report about Sage Days 24 which took place last week at the Research Institute for Symbolic Computation (RISC), located in a small town called Hagenberg just outside Linz in Austria. Many thanks for the organizers for inviting me!

Since I'm starting as a Ph.D. student at RISC in October, it was nice to get an early view of the site and meet some current students and staff. The location is quite beautiful, my only complaint being the extremely high temperature last week (they say the weather is more normal most of the year!).

SD24 was titled "Symbolic Computation in Differential Algebra and Special Functions", which pretty accurately describes the topics covered. Some points of interest:

William Stein talked about his vision for Sage (short and long term), including goals for special functions support.

Frédéric Chyzak gave a talk about the Dynamic Dictionary of Mathematical Functions. I really like the approach of starting from a minimal definition of a special function (a differential equation with initial conditions) and generating series expansions, Chebyshev approximations (etc.) algorithmically.

Nico Temme talked about numerical evaluation of special functions, which was familiar grounds to me, but with much food for thought.

I met Manuel Kauers, my future supervisor, who gave a neat presentation of some recent research.

There were many other interesting talks and discussions as well, and I gave a talk about special function evaluation in mpmath (based on my SD23 talk). And of course, I met various other Sage developers and got some coding done as well.

I had hoped to get generalized hypergeometric functions into Sage during SD24. There is now a patch, but it still needs some more work.

I also implemented parabolic cylinder functions (PCFs) in mpmath, the last remaining chapter of hypergeometric functions listed in the DLMF (mpmath now covers chapters 1-20, 22, 24-25, partially 26-27, and 33). Code commit here.

Technically, parabolic cylinder functions are just scaled (linear combinations of) confluent hypergeometric functions or Whittaker functions, but they are a bit tricky to compute due to cancellation and branch cuts.

An example from Nico Temme's talk was to evaluate Dν(z) with ν = -300.14 and z = 300.15 (Maple 13 takes 5 seconds to give an answer that has the wrong sign and is off by 692 orders of magnitude). The new pcfd function in mpmath instantaneously (in about a millisecond) gives the correct result:

>>> pcfd(-300.14, 300.15)
6.83322814925713e-10526
>>> mp.dps = 30
>>> pcfd('-300.14', '300.15')
6.83322814923312844480669009487e-10526


All the curve plots from DLMF 12.3 can be reproduced as follows:

f1 = lambda x: pcfu(0.5,x)
f2 = lambda x: pcfu(2,x)
f3 = lambda x: pcfu(3.5,x)
f4 = lambda x: pcfu(5,x)
f5 = lambda x: pcfu(8,x)
plot([f1,f2,f3,f4,f5], [-3,3], [0,3])



f1 = lambda x: pcfv(0.5,x)
f2 = lambda x: pcfv(2,x)
f3 = lambda x: pcfv(3.5,x)
f4 = lambda x: pcfv(5,x)
f5 = lambda x: pcfv(8,x)
plot([f1,f2,f3,f4,f5], [-3,3], [-3,3])



f1 = lambda x: pcfu(-0.5,x)
f2 = lambda x: pcfu(-2,x)
f3 = lambda x: pcfu(-3.5,x)
f4 = lambda x: pcfu(-5,x)
plot([f1,f2,f3,f4], [-8,8], [-6,6])



f1 = lambda x: pcfv(-0.5,x)
f2 = lambda x: pcfv(-2,x)
f3 = lambda x: pcfv(-3.5,x)
f4 = lambda x: pcfv(-5,x)
plot([f1,f2,f3,f4], [-8,8], [-6,6])



f1 = lambda x: pcfu(-8,x)
f2 = lambda x: pcfv(-8,x)*gamma(0.5-(-8))
f3 = lambda x: hypot(f1(x), f2(x))
plot([f1,f2,f3], [-6,6], [-120,120])



f1 = lambda x: diff(pcfu,(-8,x),(0,1))
f2 = lambda x: diff(pcfv,(-8,x),(0,1))*gamma(0.5-(-8))
f3 = lambda x: hypot(f1(x), f2(x))
plot([f1,f2,f3], [-6,6], [-220,220])



A little more information can be found in the mpmath documentation section for PCFs.

Thanks again to the NSF grant enabling this work.

by Fredrik Johansson (fredrik.johansson@gmail.com) at July 27, 2010 10:19 PM