If you are going to publish an academic paper for an international readership, what language will you use? You won’t use Russian, Mandarin, French, Spanish, in spite of their huge numbers of native speakers: you will write in English. This is simply because English has become the dominant language of international communication. Every now and then you may find some author writing a windy expostulation as to why English is “better” than other languages: it will be rubbish, because English is demonstrably no better than any other language. In fact in many ways it’s a terrible language: maddenly inconsistent, impossible spelling, grammar that no two people can agree on – it’s simply an historical accident that it has its current position as the world’s most popular second language. After all, only a few hundred years ago, at least in the Western world, Latin was the dominant common language, so who knows – maybe English will in its turn be supplanted by something else.

Note that only in 2011, in their Melbourne meeting, the International Association of Plant Taxonomy decreed that English was an acceptable alternative to Latin for the formal description of a new species.

Just recently I was looking at a international conference to be held in France, where the main language was to be English, but the organizers have planned for a bilingual conference, the other language being of course French. Even so: “We aim that at most 30% of the contributions … will be in French.”

Next, back to software.

More and more papers in mathematics and mathematics education now include computer code: a few lines, or indeed entire programs, written either to accompany the paper, or as a major part of it. This is a trend I really like; I believe that there are huge changes to the way in which mathematics is done and perceived, and computer-based experimental or experiential mathematics is fast becoming mainstream.

What happens if a paper is written in which the code is in Mathematica, or Maple? This means that readers who *don’t* use that software are unable to experiment with the code, or to get to grips with the full material of the paper. I have found this very frustrating time and again. Sometimes the authors give pseudocode, but not always. And sometimes the code given is simple and clear enough that it is almost pseudocode itself, and such easily translatable into another language. But again, not always. Mathematica writers in particular have a tendency to produce obscure code, and such code can look like the offspring of an unholy coupling between BASIC and Befunge:

colSeq[x_] := NestWhileList[ Which[ EvenQ[#], #/2, True, 3*# + 1] &, x, # \[NotEqual] 1 &]

But of course each language has its own quirks and peccadilloes, and even with the best will in the world a writer who has been used to one language for years may write what appears to be simple and clear – which it may be – but only to users of that language. The trouble is that as far as commerical systems go, hardly anybody is proficient in more than one, and hardly anybody has access to both: an institution may standardize on one or the other, but very rarely both. So if you use Maple or Mathematica, users of the *other* system will be left out.

I am guilty of this myself, I have published papers which use Maple.

I think that there should be a common “second language” in which all authors publish. For symbolic algebra alone there’s a lot to choose from: Maxima, Sage, Reduce, Axiom, SymPy to name but five. Note that SageMathCloud allows users to collaborate, share LaTeX papers, and experiment with such software all for the cost of creating a free account. (It’s worth noting, though, that the free accounts have certain space and computational restrictions; to obtain more space or less restrictions you have to pay for it.)

It seems to me that writers of mathematical papers which include computing should very seriously think about the use of such open systems, and editors of journals should be more proactive in encouraging authors. If you write a paper which is heavily based around Mathematica (for example), and is not easily translatable to another language, then its rightful place is not in a mathematics journal, but a trade magazine such as the Mathematica Journal. After all, published mathematics is available for averybody, anyhere, to use withough restrictions; a theorem is available to all. But locking up material in commercial software flies in the face of openness in mathematics publishing: it makes it harder for readers, and harder for other researchers to check your work. Don’t do it.

When you write your paper which uses your favorite commercial computing platform, ask yourself: am I happy to alienate all readers who use other systems? Am I happy to halve my readership?

]]>,

with

would make a reasonable PRNG. (It doesn’t: it’s too slow, and fails some tests). But this led me into some programming for testing. First, here it is in C, using the multiple precision GMP library:

/* A program to compute some values x[i] = a^x[i-1] mod p, with a = 7, p = 2^31-1. Compile with: gcc modpowers.c -o modpowers -lgmp -std=gnu99 -g */ #include <stdio.h> #include "gmp.h" #define pp 2147483647 mpz_t y,b,p; static mpz_t x; unsigned long power(void) { mpz_powm(y,b,x,p); // Set y = b^x mod p mpz_set(x,y); // x = y return (mpz_get_ui(x)); } int main() { mpz_init_set_ui(b,7); // Initialize values for use in GMP functions mpz_init_set_ui(p,pp); mpz_init_set_ui(x,7); mpz_init(y); for (int i = 0; i < 1000000; i++) { unsigned long t = power(); if ((i % 100000) == 0) printf("%10i,%10lun",i,t); } return 0; }

And here is its timing, after compiling and running:

$ time ./modpowers 0, 823543 100000,1919783493 200000, 198289041 300000,1263498529 400000, 887186099 500000, 944134154 600000,1803260766 700000, 555710010 800000, 469238760 900000,1834709953 real 0m0.904s user 0m0.900s sys 0m0.000s

So: a million values in less than a second.

Now, because I’m not very sure of my C skills, I often use Sage to check whether I’ve implemented a function properly in C. So here’s Sage doing the same thing:

def printpowers(n): a,p = 7,2^31-1 for i in range(10^n): a = power_mod(7,a,p) if mod(i,10^(n-1))==0: print i,a

We can check that `printpowers(6)` gives the same results as the output of the C program above. But:

sage: timeit('printpowers(6)',repeat=1) 5 loops, best of 1: 73.8 s per loop

As you see, the time is far greater.

Now, I know I can write code in Cython, and use that within Sage, but sometimes it’s nice – especially given some highly optimized and specialized libraries for C – to be able to work directly with C. Anyway, I’m enjoying the huge speed of compiled code.

]]>It is easy to see that this works, as the product is equal to zero if and is equal to one if .

This isn’t particularly easy to program, and in fact methods such as Newton’s divided differences or Neville’s algorithm are used to obtain the polynomial.

But a method introduced by Gabor Szegö provides a very simple form of Lagrange’s polynomial.

Start with defining

.

Then

This is obtained immediately from the product rule for arbitrary products, and using the fact that the derivative of each individual term of is one. This means that in particular

because all other terms of contain an term and therefore produce zero for .

This means that the coefficient of in the Lagrangian polynomial can be written as

and so the polynomial can be written as

.

Here is an example, with and . First, Maxima:

`(%o1) xs:[-2,1,3,4];`

(%o2) ys:[-3,-27,-23,3];

(%o3) define(pi(x),product(x-xs[i],i,1,4));

(%o4) define(pid(x),diff(pi(x),x));

(%o5) define(P(x),sum(pi(x)/(x-xs[i])/pid(xs[i])*ys[i],i,1,4));

(%o6) ratsimp(P(x));

Now Sage:

sage: xs = [-2,1,3,4] sage: ys = [-3, -27, -23, 3] sage: pi(x) = prod(x-i for i in xs); pi(x) (x - 4)*(x - 3)*(x - 1)*(x + 2) sage: pid(x) = diff(pi(x),x); sage: P(x) = sum(pi(x)/(x-i)/pid(i)*j for (i,j) in zip(xs,ys)) sage: P(x).collect(x) x^3 - 11*x - 17

And finally, on the TI-nspire CAS calculator:

Note that all the mathematical symbols and programming constructs are available through the calculator’s menus.

Notice that this approach requires no programming with loops or conditions at all – it’s all done with simple sums and products.

]]>My interest here is the permutations which are used for the line endings. If you look carefully, you’ll see that the same permutation is used each time. This means that the sestina can be described in terms of powers of a single permutation. In cyclic notation, the first permutation 615243 can be written as

.

That is, the ending of line 1 becomes the ending of line 2 in the next stanza, the ending of line 2 becomes the ending of line 4 in the next stanza, and so on. Here’s Sage to do all the hard work:

sage: S = SymmetricGroup(6) sage: p = S((1,2,4,5,3,6)) sage: for i in range(6): print i+1,p^i ....: 1 () 2 (1,2,4,5,3,6) 3 (1,4,3)(2,5,6) 4 (1,5)(2,3)(4,6) 5 (1,3,4)(2,6,5) 6 (1,6,3,5,4,2)

Look at stanza 5 for example, The permutation is 451362. This means that 1 goes to the third place, 2 to the sixth place, 3 to the fourth place and so on. But this is given by the cycles

.

If we want to print out the permutations as given above, that is easy:

sage: q = p.inverse() sage: for i in range(6): ....: qi = q^i ....: print i+1,[qi(i) for i in range(1,7)] ....: 1 [1, 2, 3, 4, 5, 6] 2 [6, 1, 5, 2, 4, 3] 3 [3, 6, 4, 1, 2, 5] 4 [5, 3, 2, 6, 1, 4] 5 [4, 5, 1, 3, 6, 2] 6 [2, 4, 6, 5, 3, 1]

The sestina can now described as follows: in stanza , the permutations of the line endings are given by where . I wonder how much of the theory of permutation groups was known to Artaud Daniel?

]]>Not long after Aaron’s 715th homer, Carl Pomerance, then at the University of Georgia, and two others, noticed two facts about the numbers 714 and 715:

- The two numbers between them factored into the first seven primes:
and

.

- The sums of the prime factors of each were the same:

Pomerance and his colleagues wrote a paper called “714 and 715” which he later described as “humorous” discussing these numbers. This paper, had the effect of catching the eye of Paul Erdős, who suggested that he visit Pomerance in Georgia, thus starting a long and fruitful collaboration between the two (at least 40 joint papers).

In honour of the two baseball players, two consecutive integers the sum of whose prime factors (with multiplicity) are equal, are called *Ruth-Aaron pairs*. It’s not hard to set up a brute force program to list them:

sage: def S(n): return sum(i*j for i,j in factor(n)) ....: sage: for k in range(1,100000): ....: if S(k)==S(k+1): ....: print k ....: 5 8 15 77 125 714 948 1330 1520 1862 2491 3248 4185 4191 5405 5560 5959 6867 8280 8463 10647 12351

… and so on. This sequence is A039752 in the OEIS.

It is not yet known whether there are infinite Ruth-Aaron pairs, but it is known, thanks to Pomerance and Erdős, that they are quite rare; in fact Pomerance proved that for any integer , the number of integers for which was bounded as

and that the sum of the reciprocals was bounded.

In 1995 Emory University awarded honorary degrees to both Aaron and Erdős. Pomerance, who was then at Emory, asked for a baseball – several had been provided for Aaron to sign – and asked both Aaron and Erdős to sign it. “I joke that Aaron should have Erdős-number 1 since, though he does not have a joint paper with Erdős, he does have a joint baseball.”

]]>or a picture such as this:

illustrating all possible throws of two dice. From either of these the number of ways of obtaining a sum is given by:

sum: 2 3 4 5 6 7 8 9 10 11 12 #: 1 2 3 4 5 6 5 4 3 2 1

From a table such as this it is easy to answer all probability questions from the book. Very few books, however, go into the question about sums from three or more dice. I imagine that there is little further learning of probability to be gained by thus extending the problem, so for multiple “throws” coins are used rather than dice.

However, the mathematics is quite fun. Suppose (6-sided, fair) dice are thrown. In how many ways can the sum be obtained? Let’s call this number . From the table above, you can see that, for example . But what is the value, for example, or , or of ?

Look at the case . We are interested in the number of sums where . Such a sum should immediately suggest a generating function, and for this example the generating function is

Thus . And in general is the coefficient of in . This result is of course also given on Mathworld. And we can calculate these with Sage:

sage: dx = x+x^2+x^3+x^4+x^5+x^6 sage: expand(dx^3).coeff(x,10) 27

There’s nothing to stop us trying larger numbers of dice and larger sums, for example 10 dice and the sum of 34 for the value of :

sage: expand(dx^10).coeff(x^34) 4325310

However, this can be slow. For large values of Sage has to do a lot of computation. When I tried with , my computer ground to a halt as all memory was sucked up by Sage, which crashed a bit later. (For those of you concerned about Sage abuse, I gave it a nice cup of tea after a restart and we’re still good friends.) So we would like a more efficient method of computing for large and .

Note that by the definition of as a coefficient of , and as we are using 6-sided dice, if follows that

.

If we let for less than or greater than we can produce a simple dice program:

sage: def dice(k): d = 6*[1] for i in range(k-1): t = 5*[0] + d + 5*[0] d = [sum(t[i:i+6]) for i in range(len(t)-5)] return d ....:

Then:

sage: dice(2) [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1] sage: dice(3) [1, 3, 6, 10, 15, 21, 25, 27, 27, 25, 21, 15, 10, 6, 3, 1]

Notice that the outcome of `dice(k)` gives the number of sums for all starting at . So then

sage: def t(k,n): return dice(k)[n-k]

Then:

sage: t(2,10) 3 sage: t(3,10) 27 sage: t(100,350) 15237092858379903128111407924086725562812976591205826140530848189030092709496

Big enough for ya?

**Addendum**

Thanks to a correspondent (see below) the use of polynomial rings vastly simplifies matters.

For example, without doing any programming:

sage: R.<x> = PolynomialRing(ZZ) sage: dx = R([1]*6)*x sage: dx x^6 + x^5 + x^4 + x^3 + x^2 + x sage: (dx^3)[10] 27 sage: (dx^100)[350] 15237092858379903128111407924086725562812976591205826140530848189030092709496

All results are given instantaneously. The nice thing about his approach is that it enables us to mix and match dice. Suppose we throw 11 cubical dice, 13 octahedral dice, and 15 dodecahedral dice. In how many ways can we obtain the sum of 200?

In one step:

sage: ((R([1]*6)*x)^11*(R([1]*8)*x)^13*(R([1]*12)*x)^15)[200] 69232087336767815011624465024995662]]>

Consider years which aren’t leap years. To start, create a list of the number of days in each month:

sage: months = [31,28,31,30,31,30,31,31,30,31,30,31]

Now we make a cumulative sum containing the total numbers of days of the year until the start of each month:

sage: cmonths = [0] sage: for x in months[:11]: ....: cmonths += [x+cmonths[-1]] ....: sage: cmonths [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334]

Finally, we turn this last list into a list of days on which each 13th of the month falls:

sage: thirteens = [mod(x+13,7) for x in cmonths] sage: thirteens [6, 2, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]

Notice that this is a complete set of residues modulo 7:

sage: set(thirteens)==set(range(7)) True

This means that no matter what day on which a year starts, in other words, no matter what value (mod 7) is added to that list, there will be at least one value equal to 5 – a Friday. For 2011, January 1 was a Saturday, so the zeroth day was a Friday:

sage: [x+5 for x in thirteens] [4, 0, 0, 3, 5, 1, 3, 6, 2, 4, 0, 2]

The five is in the fifth place, indicating the fifth month: May. In 2015, January 1 will be on a Thursday, so the zeroth day is Wednesday:

sage: [x+3 for x in thirteens] [2, 5, 5, 1, 3, 6, 1, 4, 0, 2, 5, 0]

Here there are three Friday 13’s: in February, March and November. Note that this is the maximum possible, as three is the highest count for any value in the “thirteens” list.

And here’s the same thing for leap years:

sage: months = [31,29,31,30,31,30,31,31,30,31,30,31] sage: cmonths = [0] sage: for x in months[:11]: cmonths += [x+cmonths[-1]] ....: sage: thirteens = [mod(x+13,7) for x in cmonths] sage: thirteens [6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5] sage: set(thirteens)==set(range(7)) True

Again, the list is a complete set of residues modulo 7, and the largest number of occurrences is 3, in the months January, April and July. These months will have a Friday 13 if the year begins on a Sunday, and the next such year will be next year: 2012.

]]>

assuming that there are only 365 days in a year, and that each birthday is equally likely. This expression can be more concisely written as

The probability of at least two birthdays being the same is then

For this value is slightly greater than 0.5:

sage: def perm(n,k): return binomial(n,k)*factorial(k) ....: sage: (1-perm(365,23)/365^23).n() 0.507297234323985

This fact that birthday “collisions” are surprisingly likely for a relatively small group, is the foundation for much of the theory of cryptographic hash functions, where security is related to the difficulty of finding collisions: two different inputs with the same output.

But recently I discovered that at least three people known to me had the same birthday. What were the odds of this, I wondered? In general, how many people do you need to have better than even odds for at least *three* people to share a birthday? Being generally pretty poor at probability (at school I answered a probability question in a local mathematics magazine, and had my answer printed, only to discover later that it was in fact wrong), I did a search. The best answer, with a nice explanation, is here.

Here’s how this author, Dr Rick, solved it. As for the simpler birthday problem above, first find the probability that any birthday is shared by at most two people. We can build this answer up in stages. To start, suppose there are people, what is the probability that there are exactly four pairs who share (different) birthdays?

Start with assuming that the first two people have the same birthday, and the second pair has the same birthday (which is different to the birthday of the first pair), and then the third pair share a birthday (again which is different to the first two pair birthdays) and similarly for the fourth pair. This probability can be computed by choosing any four birthdays for the four pairs, and ensuring that all the other people have different birthdays. Start by noting that there are

ways of choosing four different birthdays (one for each pair) and

ways of choosing the first pair. This leaves

ways of choosing the second pair. And the number of ways of choosing the third and fourth pairs will be

and

respectively. Then we require that the other people all have different birthdays chosen from the remaining 361 possible days. Putting all this together gives us the total probability of exactly fours pairs of people, each pair of which share a birthday:

where the last expression is of course the probability of people having different birthdays from a total of possible days.

This expression can be simplified. First note that

Now the above expression can be written as

Now we can also express the permutation and binomial coefficient as factorials:

This means that the probability of exactly pairs of equal birthdays is

and so the total probability of pairs of birthdays (but no triples) is

Thus the probability of at least one trio of birthdays is

This is the same formula which is given (without derivation) in Anirban DasGupta, The matching, birthday and the strong birthday problem: a contemporary review, Journal of Statistical Planning and Inference 130 (2005), 377-389. (For this reference, I am indebted to Michael Lugo on Mathematics StackExchange).

Now for some numerical experiments:

sage: def trio(n): return (1-sum((factorial(365)*factorial(n))/ ....: (factorial(i)*factorial(n-2*i)*factorial(365-n+i)*2^i*365^n) ....: for i in range(n//2+1))).n() ....: sage: trio(87) 0.499454850631401 sage: trio(88) 0.511065110624730

and we see we need a group of 88 people to have better than even odds that three of them share a birthday.

]]>.

But here’s a generalization of that which has been attributed to Joseph Liouville (1809 – 1882). Pick any number, say 56, and write down all of its divisors:

Now, for each number in that list, write down the *number* of its divisors:

For example, 7 has 2 divisors (1 and 7), and 14 has 4 divisors (1, 2, 7 and 14). But for this second list, the sum of its cubes equals the square of its sum!

.

Here’s a quick check with Sage:

sage: n = 56 sage: L=[number_of_divisors(i) for i in divisors(n)];L [1, 2, 3, 2, 4, 4, 6, 8] sage: sum(L)^2,sum(i^3 for i in L) (900, 900)

And now to prove this result. Start by saying that a list has the *square-cube (SC) property* if the sum of its cubes equals to the square of its sum. So any list has the SC property, as does the list . Also define the pairwise product of two lists and to be the list consisting of all possible products of pairs of elements from and . In other words:

where of course is the Cartesian product. From the definition then it is easy to show that,

For example, if and then

with sum 60, which is equal to the product of the sums of and . Note that

It follows immediately from this that if and are two lists each of which has the SC property, then so does . To see this, suppose that

and

Multiplying these together produces

.

The right hand side is equal to

By the same reasoning as above, the left hand side is equal to

By induction, if is a collection of lists all with the SC property, then has the SC property.

Consider and its decomposition into prime factors:

.

For any prime power the number of divisors of is ; the divisors are all the powers of from 1 to . And the *numbers* of divisors of all those prime powers are . Consider now . The divisors are for all values of between 1 and , and all values of between 1 and . The number of divisors of are . From this it follows that the number of divisors of the divisors of is

.

and hence which has the SC property. The general result follows by induction on the number of distinct prime factors of .

Published proofs and further discussion can be found in “An Interesting Number Fact” by David Pagni, The Mathematical Gazette, Vol. 82, No. 494, Jul., 1998, and “Generalising ‘Sums of Cubes Equal to Squares of Sums'” by John Mason, The Mathematical Gazette, Vol. 85, No. 502, Mar., 2001.

]]>void code(long* v, long* k) { unsigned long y=v[0], z=v[1], sum=0, /* set up */ delta=0x9e3779b9, n=32; /* a key schedule constant */ while (n-->0) { /* basic cycle start */ sum += delta; y += ((z<<4) + k[0]) ^ (z + sum) ^ ((z>>5) + k[1]); z += ((y<<4) + k[2]) ^ (y + sum) ^ ((y>>5) + k[3]); } /* end cycle */ v[0]=y ; v[1]=z ; }

It is in fact easier to show the code than it is to describe the cipher in words! It consists of two Feistel steps, one after the other forming a “cycle”, and there are 32 such cycles in the encryption step. The authors decided that a large number of rounds would overcome deficiencies in the trivial key schedule. The cipher is easily translated into Sage:

def tea(plaintext,key): n = 32; N = 2^n delta = ZZ('0x9e3779b9'); sm = 0 [z,y] = ZZ(plaintext).digits(N,padto=2) [k3,k2,k1,k0] = ZZ(key).digits(N,padto=4) for i in range(n): sm = (sm + delta)%N y = (y+ (((z<<4)+k0) ^^ (z+sm) ^^ ((z>>5)+k1)))%N z = (z+ (((y<<4)+k2) ^^ (y+sm) ^^ ((y>>5)+k3)))%N return hex(N*y+z)

There have been some successful attacks on TEA, and several iterations later, the most recent version is XXTEA, which can be described as:

void xxtea_full_cycle(uint32_t *v, int n, uint32_t*key, int cycle) { uint32_t sum, z , y , e; int r; sum = cycle*0x9e3779b9; e = sum>>2; for (r = 0; r < n; r++) { z = v[(r+n−1)%n]; // the left neighboring word y = v[(r+1)%n]; // the right neighboring word v[r] += ((z>>5^y<<2)+(y>>3^z<<4))^((sum^y)+(key[(r^e)%4]^z)) ; } } void xxtea (uint32_t *v, unsigned int n, uint32_t *k) { int i , cycles = 6+52/n; for (i = 1; i < cycles; i++) xxtea_full_cycle(v , n , k , i); }

Again, this is not as safe as it looks, but it is nonetheless remarkable that such a simple construction can yield at least some non-trivial security.

Another super-simple cipher is Treyfer, developed by Gideon Yuval in 1997. It has a key and block size of 8 bytes each. In the article introducing it, he claimed: “By using a large number of rounds, we hope to be able to scrounge an Sbox out of nowhere, in an environment for which even TEA and the SAFERs are gross overdesign.” Here it is:

for(r=0; r<NumRounds; r++) { text[8]=text[0] ; for(i=0; i<8; i++) { text[i+1]=(text[i+1] + Sbox[(key[i]+text[i])%256])<<<1; // rotate i left } text[0]=text[8] ; }

It uses an S-box which is not prescribed; any 256 x 8 bytes will do, and these bytes can be obtained from anywhere, again minimizing the effective size of the cipher. Yuval showed how the entire cipher can be implemented in only 30 bytes.

]]>