Normally discrete convolution is written as follows:
It is not immediately obvious from this that
This formula is obviously symmetric in
Let
This emphasizes that the
There is one subtle difference. In this alternate representation, it very much matters what the domain
of
In many combinatorial situations this makes no difference and may even be preferable. If, however, you
are doing something like a short-time Fourier transform, then you probably don’t want to include an
infinite number of entries (but you probably aren’t indexing by
Let’s prove that
and we’re done. It’s clear the associativity of convolution comes from the associativity of
addition and distributivity. In fact, the commutativity also came from the commutativity of addition. This
suggests a simple but broad generalization. Simply replace the
Usually
As an update: Conal Elliott uses a similarly generalized notion of convolution in
Generalized Convolution and Efficient Language Recognition.
In particular, the generalization using an arbitrary binary function Vec n x
as Fin n -> x
.
With traditional convolution, we’d still have a problem since (+)
requires its arguments
to be the same type and the type of the result, so not Fin n -> Fin m -> Fin (m + n - 1)
.
This isn’t a problem for
Here’s some code for the free monoid (i.e. lists) case:
import Data.Monoid
import Data.List
class Monoid m => CommutativeMonoid m
instance Num a => CommutativeMonoid (Sum a)
-- Overly generalized convolve
ogconvolve :: (CommutativeMonoid m) => (a -> b -> m) -> (n -> [(j, k)]) -> (j -> a) -> (k -> b) -> n -> m
= mconcat (map (uncurry (\j k -> mul (f j) (g k))) (factor n))
ogconvolve mul factor f g n
gconvolve :: Num m => (n -> [(n, n)]) -> (n -> m) -> (n -> m) -> n -> m
= getSum (ogconvolve (\a b -> Sum (a*b)) factor f g n)
gconvolve factor f g n
lconvolve :: Num m => ([a] -> m) -> ([a] -> m) -> [a] -> m
= gconvolve (\as -> zip (inits as) (tails as)) lconvolve
You may have noticed that we never actually use
all (\(j,k) -> n == j `oplus` k) (factor n)
and also that
== nub (factor n) factor n
i.e. no duplicates. (Conceptually, factor
spits out a set, indeed the graph
of the relation
The commutative monoid constraint and mul
function were just for the heck of it, but why a commutative
monoid and not an arbitrary monoid? Well, we don’t want the result to depend on how factor
spits out
the factors. In other words, if it actually did return a set then we can’t depend on the order of the
elements in the set if we want a well-defined function.
Here’s where I tell you that lconvolve
is an important function for something. I suspect it or a
variant probably is, but I don’t know. Here’s another monoid case, commutative this time, that
definitely is important and interesting: Dirichlet convolution.
Here’s the typical bad definition:
These are the coefficients of the product of two Dirichlet series. For example,
We again see a situation where the correspondence doesn’t just jump out at you (or at least it didn’t to me originally) until you realize the above sum can be written:
then it’s pretty easy to see that it is right. We can start doing a lot of number theory with the above combined with the Euler product formula:
where
where we’ve used the formula for the sum of a geometric series.
So