21 June 2022

Primorials and Kronecker products

Primorials

I am always amazed at the way mathematicians find a meaning or a use for obscure sequences and mathematical operations. And here's another one: primorial P(n) is defined as the product of the first n prime numbers. That is true whether or not you accept 1 as the first prime, but apparently P(0) is 1 which neatly sidesteps that argument.

It's easy to see that successive primorials increase fast. We are asked to generate the first 10, and P(9) is already over 223 million, and after that we are quickly into BigInt territory.

As this is a relatively simple task I chose to generate the primes rather than using a module and my algorithm looks like this:

k = 1
Loop j from 2 until we've found P(9)
    Next j if j is divisible by any prime we've found so far
    So j is prime, save it
    k = k * j, and k is the next primorial

I'm sure someone will come with a one-liner for this, but as always I tens to prioritise lucidity over brevity.

Kronecker products

You come across Leopold Kronecker's musings all over the place, and I see that at least a dozen mathematical 'things' are named after him.  Fortunately, this one isn't too hard to follow, thanks to someone giving the key to solving it in Wikipedia, albeit in very small print.

As with some other recent challenges, it takes more lines code to display the data neatly  than to perform the required calculation.

I used two helper functions. First is quorem which takes two arguments, a dividend and a divisor, and returns the quotient and the remainder as per primary school division.  The second is show which simply displays a matrix with the columns neatly lined up. I use that to display the two input matrices (A and B) and the resulting product matrix (K).

Wikipedia kindly gives us the formula for each element K(i, j) as a function of two elements of A and B. The calculation of which elements of A and B are needed involves some modular arithmetic, which is where quorem comes in.

The show function makes two passes over the matrix to be displayed. In the first pass it determines which element is the widest, for which Perl's length function is useful as it intrinsically copes with minus signs. The cell width is then made one space wider than the widest number for a pleasing result.

I chose to store the 3 matrices as 2-dimensional arrays - actually arrays of references, so that element X(i, j) is $X->[$i]->[$j]. This nicely parallels the mathematical representation.


No comments:

Post a Comment