cc3_2.py

#

Here we calculate the 3-term connection coefficients. I glued pycco and MathJax together. This gives a nice documentation of the code in form of literate scientific programming.

However, there is a bug in my code: The value this programm computes, are not equal to the ones from Resnikov and Wells, 1998. Except for l=m. Find the raw python code in my Github repository. Please let me know if you find the issue!

with

import itertools
import warnings

import numpy as np
from scipy.misc import factorial

from moments import moment
from scaling_coefficients import db3, daubechies_wavelets
#
#

Restriction to Fundamental Connection Coefficients

def threeterm_connection_coefficients(a, d1, d2, d3):
#

The 3-term connection coefficients are defined as which can be transformed by a change of variables with and to

    if d1 == 0:
        idx, indices, Λ = fundamental_threeterm_connection_coefficients(a, d1, d2, d3)
        idx2 = lambda i,j,k: idx(j-i, k-i)
        return idx2, indices, Λ
    else:
#

Using integration by parts we can focus on the case

        idx1, indices1, Λ1 = threeterm_connection_coefficients(a, d1-1, d2+1, d3)
        idx2, indices2, Λ2 = threeterm_connection_coefficients(a, d1-1, d2, d3+1)
        assert indices1 == indices2
        return idx1, indices1, -Λ1 - Λ2
#

Calculation of Fundamental Connection Coefficients

def fundamental_threeterm_connection_coefficients(a, d1, d2, d3):
#

Our wavelet has non-zero scaling coefficients where is the genus.

    N = a.size 
    aindices = range(N)
    d = d1 + d2 + d3
#

The fundamental connection coefficients are just non-zero for

    Tindices = list(set((l,m) for l,m in itertools.product(range(-(N-2), (N-2)+1), repeat=2)
                      if abs(l-m) < (N-1)))
    idx = lambda l,m: Tindices.index((l,m))
    M = 3*N**2 - 9*N + 7
    assert len(Tindices)
#

The Daubechies wavelet of genus has just as many vanishing moments and we must not calculate higher derivatives than !

    if np.amax([d1,d2,d3]) >= N/2:
        msg = 'Calculation of connection coefficients for {},{},{} > g = N/2 is invalid!'.format(d1,d2,d3)
        warnings.warn(msg)
#

Consequences of Compactness

We exploit the fact that which means for the connection coefficients using the chain rule with .

Using a change of variables and remembering we find

This gives a system of equations of the form where .

    T = np.zeros([len(Tindices), len(Tindices)])
    
    for l,m in Tindices:
        for i,j,k in itertools.product(range(N), repeat=3):
            if (2*l+j-i, 2*m+k-i) not in Tindices:
                continue # skip the Λ which are zero anyway
            T[idx(l,m), idx(2*l+j-i, 2*m+k-i)] += a[i]*a[j]*a[k]

    T -= 2**(1-d)*np.eye(len(Tindices))
    b = np.zeros([len(Tindices)])
#

Consequences of Moment Equations

If we differentiate the moment equation times with , we yield the equation Then multiplying by for some fixed , and integrating, we gain Finally, we perform a change of variables Similar equations hold for and .

    M = np.zeros([d1, len(Tindices)])
    j = 0 if (d2 % 2) == 0 else 1
    k = 0 if (d3 % 2) == 0 else 1
    for q in range(d1):
        for i in range(-(N-2), (N-2)+1):
            if (j-i, k-i) in Tindices:
                M[q, idx(j-i, k-i)] += moment(a, i, q)
    A = np.vstack([T,M])
    b = np.hstack([b, np.zeros([d1])])

    M = np.zeros([d2, len(Tindices)])
    i = 0 if (d1 % 2) == 0 else 1
    k = 0 if (d3 % 2) == 0 else 1
    for q in range(d2):
        for j in range(-(N-2), (N-2)+1):
            if (j-i, k-i) in Tindices:
                M[q, idx(j-i, k-i)] += moment(a, j, q)
    A = np.vstack([A,M])
    b = np.hstack([b, np.zeros([d2])])

    M = np.zeros([d3, len(Tindices)])
    i = 0 if (d1 % 2) == 0 else 1
    j = 0 if (d2 % 2) == 0 else 1
    for q in range(d3):
        for k in range(-(N-2), (N-2)+1):
            if (j-i, k-i) in Tindices:
                M[q, idx(j-i, k-i)] += moment(a, k, q)
    A = np.vstack([A,M])
    b = np.hstack([b, np.zeros([d3])])
#

Normalization of the Coefficients

Finally we differentiate the moment equation times, yielding Similar equations hold for and . Multiplying these equations and integrating gains Again with a change of variables this yields

    M = np.zeros([1, len(Tindices)])
    i = 0
    for j,k in itertools.product(range(-(N-2), (N-2)+1), repeat=2):
        if (j-i, k-i) in Tindices:
            M[0, idx(j-i, k-i)] += moment(a, j, d2)*moment(a, k, d3)
    A = np.vstack([A,M])
    b = np.hstack([b, [factorial(d1)*factorial(d2)*factorial(d3)]])

    Λ, residuals, rank, singular_values  = np.linalg.lstsq(A, b)

    if (residuals > 1e-30).any():
        msg = 'Residuals {} of connection coefficients exceed 10**-30!'.format(residuals)
        warnings.warn(msg)

    return idx, Tindices, Λ
#
def test():
    from test_cc3 import cc3_100
    idx, Tindices, Λ = threeterm_connection_coefficients(db3, 1, 0, 0)

    N = len(db3)
    for l,m in itertools.product(range(-(N-2), (N-2)+1), repeat=2):
        a = Λ[idx(0,l,m)] if abs(l-m) < (N-1) else 0
        b = cc3_100[(l,m)]

        print(l,m, a, b, (a-b)/(b if b != 0 else 1))

if __name__  == '__main__':
    test()