ListConvolve

The next cell demonstrates the basic use of ListConvolve.

Off[General :: spell1] ;  Clear["Global`*"] ;   ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}]

{a4 b1 + a3 b2 + a2 b3 + a1 b4, a4 b2 + a3 b3 + a2 b4 + a1 b5, a4 b3 + a3 b4 + a2 b5 + a1 b6}


Next we see that ListConvolve is equivalent to flattening the result of a
certain matrix product.

(a4   a3   a2   a1   0    0 ) . (b1) ;   0    a4   a3   a2   a1   0      b2   0    0    a4   a ...               b6  Flatten[%] === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}]

True


The next cell shows that ListConvolve is closely related to ListCorrelate.

listA = {a1, a2, a3, a4} ;  listB = {b1, b2, b3, b4, b5, b6} ;  ListConvolve[listA, listB] === ListCorrelate[Reverse[listA], listB]

True

Specifying the "overhang" using  {K_L, K_R}


In the next cell we provide ListConvolve {-1,-1} as a third argument.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {-1, -1}]

{a4 b1 + a3 b2 + a2 b3 + a1 b4, a4 b2 + a3 b3 + a2 b4 + a1 b5, a4 b3 + a3 b4 + a2 b5 + a1 b6, a1 b1 + a4 b4 + a3 b5 + a2 b6, a2 b1 + a1 b2 + a4 b5 + a3 b6, a3 b1 + a2 b2 + a1 b3 + a4 b6}


The previous example is equivalent to the matrix product in the next cell.  
Here we have the last element of {a1, a2, a3, a4} in the upper left position
of the left matrix..  We also have the last element of {a1, a2, a3, a4} in
the lower right position of the left matrix.  The (-1) indicates last element
of {a1, a2, a3, a4}, and (-2) would indicate the second from the last element
of {a1, a2, a3, a4}.

(a4   a3   a2   a1   0    0 ) . (b1) ;   0    a4   a3   a2   a1   0      b2   0    0    a4   a ...     b6  Flatten[%] === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {-1, -1}]

True


In the next cell we provide ListConvolve {1,1} as a third argument.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, 1}]

{a1 b1 + a4 b4 + a3 b5 + a2 b6, a2 b1 + a1 b2 + a4 b5 + a3 b6, a3 b1 + a2 b2 + a1 b3 + a4 b6, a4 b1 + a3 b2 + a2 b3 + a1 b4, a4 b2 + a3 b3 + a2 b4 + a1 b5, a4 b3 + a3 b4 + a2 b5 + a1 b6}


The previous example is equivalent to the matrix product in the next cell.  
Here we have the first element of {a1, a2, a3, a4} in the upper left position
of the left matrix..  We also have the first element of {a1, a2, a3, a4} in
the lower right position of the left matrix.  The (1) indicates first element
of {a1, a2, a3, a4}, and (2) would indicate the second element of {a1, a2,
a3, a4}.

(a1   0    0    a4   a3   a2) . (b1) ;   a2   a1   0    0    a4   a3     b2   a3   a2   a1   0 ... 1     b6  Flatten[%] === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, 1}]

True


In the next cell we provide ListConvolve {1,-1} as a third argument.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}]

{a1 b1 + a4 b4 + a3 b5 + a2 b6, a2 b1 + a1 b2 + a4 b5 + a3 b6, a3 b1 + a2 b2 + a1 b3 + a4 b6,  ... 1 b6, a1 b1 + a4 b4 + a3 b5 + a2 b6, a2 b1 + a1 b2 + a4 b5 + a3 b6, a3 b1 + a2 b2 + a1 b3 + a4 b6}


The previous example is equivalent to the matrix product in the next cell.  
Here we have the first element of {a1, a2, a3, a4} in the upper left position
of the left matrix..  We also have the last element of {a1, a2, a3, a4} in
the lower right position of the left matrix.  The (1) indicates first element
of {a1, a2, a3, a4}, and (-1) indicates the last element of {a1, a2, a3, a4}.

(a1   0    0    a4   a3   a2) . (b1) ;   a2   a1   0    0    a4   a3     b2   a3   a2   a1   0 ... 0    a4  Flatten[%] === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}]

True


In the next cell we provide ListConvolve {-1,1} as a third argument. Notice
this gives the same result as

ListConvolve[{a1,a2,a3,a4},{b1,b2,b3,b4,b5,b6}]  (ie. {-1,1} is the default
for the third argument).

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {-1, 1}]

{a4 b1 + a3 b2 + a2 b3 + a1 b4, a4 b2 + a3 b3 + a2 b4 + a1 b5, a4 b3 + a3 b4 + a2 b5 + a1 b6}


The previous example is equivalent to the matrix product in the next cell.  
Here we have the last element of {a1, a2, a3, a4} in the upper left position
of the left matrix..  We also have the First element of {a1, a2, a3, a4} in
the lower right position of the left matrix.  The (1) indicates first element
of {a1, a2, a3, a4}, and (-1) indicates the last element of {a1, a2, a3, a4}.

(a4   a3   a2   a1   0    0 ) . (b1) ;   0    a4   a3   a2   a1   0      b2   0    0    a4   a ...      b6  Flatten[%] === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {-1, 1}]

True

Specifying the padding

In the next cell we provide (s) as a 4^th argument.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, s]

{a1 b1 + a2 s + a3 s + a4 s, a2 b1 + a1 b2 + a3 s + a4 s, a3 b1 + a2 b2 + a1 b3 + a4 s, a4 b1  ... b5 + a1 b6, a4 b4 + a3 b5 + a2 b6 + a1 s, a4 b5 + a3 b6 + a1 s + a2 s, a4 b6 + a1 s + a2 s + a3 s}


The next cell performs a series of Dot products that give the same result as
in the previous cell.  Notice we gave ListConvolve {1,-1} as a third
argument, and the left part of the first row starts with the first part of
{a1,a2,a3,a4}.  Also the last row ends with the last element of
{a1,a2,a3,a4}.

{ {a1, a2, a3, a4, 0, 0} . {b1, s , s , s , s , s },  {a2, a1, a3, a4, 0, 0} . ... } } ;  % === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, s]

True

In the next cell we provide {u1 ,u2, u3, u4, u5, u6} as a 4^th argument.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, {s1, s2, s3, s4, s5, s6}]

{a1 b1 + a4 s4 + a3 s5 + a2 s6, a2 b1 + a1 b2 + a4 s5 + a3 s6, a3 b1 + a2 b2 + a1 b3 + a4 s6,  ... 1 b6, a4 b4 + a3 b5 + a2 b6 + a1 s1, a4 b5 + a3 b6 + a2 s1 + a1 s2, a4 b6 + a3 s1 + a2 s2 + a1 s3}

The next cell performs a series of Dot products that give the same result  as in the previous cell. Notice the difference between giving (s) and giving  {s,t,u} as a 4^th argument.  I actually have a hard time seeing when this would be useful.

{ {a1, 0, 0, a4, a3, a2} . {b1, b2, b3, s4, s5, s6},  {a2, a1, 0, 0, a4, a3} . ... % === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, {s1, s2, s3, s4, s5, s6}]

True

To make this more clear I give another example where we give ListConvolve  a 4^th argument in the next cell.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, {s1, s2}]

{a1 b1 + a3 s1 + a2 s2 + a4 s2, a2 b1 + a1 b2 + a4 s1 + a3 s2, a3 b1 + a2 b2 + a1 b3 + a4 s2,  ... 1 b6, a4 b4 + a3 b5 + a2 b6 + a1 s1, a4 b5 + a3 b6 + a2 s1 + a1 s2, a4 b6 + a1 s1 + a3 s1 + a2 s2}


The next cell performs a series of Dot products that give the same result as
in the previous cell.

{ {a1, 0, 0, a4, a3, a2} . {b1, b2, b3, s2, s1, s2},  {a2, a1, 0, 0, a4, a3} . ... 71;} ;  % === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, {s1, s2}]

True

It's curious that providing an empty list as a 4^th argument is equivalent to providing the integer 1 as a 4^th argument.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, {}] === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, 1]

True

The next cell shows that by default ListConvolve uses the second argument  in place of a 4^th argument when none is provided.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}] === ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {1, -1}, {b1, b2, b3, b4, b5, b6}]

True

Generalizing beyond Times, Plus

In the next cell we provide ListConvolve (g) as a 5^th argument and it uses the head (g) in place of Times.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {-1, 1}, lst, g]

{g[a1, b4] + g[a2, b3] + g[a3, b2] + g[a4, b1], g[a1, b5] + g[a2, b4] + g[a3, b3] + g[a4, b2], g[a1, b6] + g[a2, b5] + g[a3, b4] + g[a4, b3]}

In the next cell we provide ListConvolve (g, h) as a 5^th and 6^th arguments respectively and it uses the heads (g) and (h) in place of  Times and Plus respectively.

ListConvolve[{a1, a2, a3, a4}, {b1, b2, b3, b4, b5, b6}, {-1, 1}, lst, g, h]

{h[g[a4, b1], g[a3, b2], g[a2, b3], g[a1, b4]], h[g[a4, b2], g[a3, b3], g[a2, b4], g[a1, b5]], h[g[a4, b3], g[a3, b4], g[a2, b5], g[a1, b6]]}

ListConvolve with matrices

In the next cell we perform a ListConvolution on matrices.

m1 = (a1   a2   a3) ;        b1   b2   b3        c1   c2   c3    m2 = (x1   x2   x3) ;        y1   y2   y3        z1   z2   z3    ListConvolve[m1, m2]

{{c3 x1 + c2 x2 + c1 x3 + b3 y1 + b2 y2 + b1 y3 + a3 z1 + a2 z2 + a1 z3}}


The next cell shows how the same ListConvolution can be done as Dot products
on parts of the matrices.

ListConvolve[m1, m2] ===  {{Part[m1, 1] . Reverse[Part[m2, 3]] + Part[m1, 2] . Reverse[Part[m2, 2]] + Part[m1, 3] . Reverse[Part[m2, 1]]}}

True

We can give ListConvolve a level specification as a 7^th argument.  The next cell shows that level (2) is the default  specification when working on matrices.

ListConvolve[m1, m2] === ListConvolve[m1, m2, {-1, 1}, m2, Times, Plus, 2]

True


In the next cell we give ListConvolve the integer (1) as a level
specification.

ListConvolve[m1, m2, {-1, 1}, m2, Times, Plus, 1]

{{c1 x1 + b1 y1 + a1 z1, c2 x2 + b2 y2 + a2 z2, c3 x3 + b3 y3 + a3 z3}}


The next cell shows how the same ListConvolution can be done as Dot products
on parts of the matrices.

mat1 = Transpose[m1] ;    mat2 = Transpose[m2] ;   ListConvolve[m1, m2, {- ... . Part[mat2, 1], Reverse[Part[mat1, 2]] . Part[mat2, 2], Reverse[Part[mat1, 3]] . Part[mat2, 3]}}

True


The next cell shows two ways of expressing the default for the third argument
of ListConvolve when working with matrices.

ListConvolve[m1, m2] === ListConvolve[m1, m2, {-1, 1}] === ListConvolve[m1, m2, {{-1, -1}, {1, 1}}]

True


I am having a hard time seeing a pattern to how a ListConvolution on matrices
is done in different cases.  I would like to have a complete understanding
for what the third argument of ListConvolve does when working with matrices,
but it's too hard to decipher.  For example I would like to understand the
result of the examples below.  

ListConvolve[m1, m2, {1, 1}]

ListConvolve[m1, m2, {{1, 1}, {-1, -1}}]

ListConvolve[m1, m2, {1, 1}, m2, Times, Plus, 1]


I also understand we can also perform a ListConvolution on tensors, but that
is also too confusing for me to think about.


Created by Mathematica  (May 16, 2004)

Back to Ted’s Tricks index page