TheAlgorithms-Python
98 строк · 3.4 Кб
1# https://en.wikipedia.org/wiki/Circular_convolution
2
3"""
4Circular convolution, also known as cyclic convolution,
5is a special case of periodic convolution, which is the convolution of two
6periodic functions that have the same period. Periodic convolution arises,
7for example, in the context of the discrete-time Fourier transform (DTFT).
8In particular, the DTFT of the product of two discrete sequences is the periodic
9convolution of the DTFTs of the individual sequences. And each DTFT is a periodic
10summation of a continuous Fourier transform function.
11
12Source: https://en.wikipedia.org/wiki/Circular_convolution
13"""
14
15import doctest16from collections import deque17
18import numpy as np19
20
21class CircularConvolution:22"""23This class stores the first and second signal and performs the circular convolution
24"""
25
26def __init__(self) -> None:27"""28First signal and second signal are stored as 1-D array
29"""
30
31self.first_signal = [2, 1, 2, -1]32self.second_signal = [1, 2, 3, 4]33
34def circular_convolution(self) -> list[float]:35"""36This function performs the circular convolution of the first and second signal
37using matrix method
38
39Usage:
40>>> convolution = CircularConvolution()
41>>> convolution.circular_convolution()
42[10, 10, 6, 14]
43
44>>> convolution.first_signal = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6]
45>>> convolution.second_signal = [0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5]
46>>> convolution.circular_convolution()
47[5.2, 6.0, 6.48, 6.64, 6.48, 6.0, 5.2, 4.08]
48
49>>> convolution.first_signal = [-1, 1, 2, -2]
50>>> convolution.second_signal = [0.5, 1, -1, 2, 0.75]
51>>> convolution.circular_convolution()
52[6.25, -3.0, 1.5, -2.0, -2.75]
53
54>>> convolution.first_signal = [1, -1, 2, 3, -1]
55>>> convolution.second_signal = [1, 2, 3]
56>>> convolution.circular_convolution()
57[8, -2, 3, 4, 11]
58
59"""
60
61length_first_signal = len(self.first_signal)62length_second_signal = len(self.second_signal)63
64max_length = max(length_first_signal, length_second_signal)65
66# create a zero matrix of max_length x max_length67matrix = [[0] * max_length for i in range(max_length)]68
69# fills the smaller signal with zeros to make both signals of same length70if length_first_signal < length_second_signal:71self.first_signal += [0] * (max_length - length_first_signal)72elif length_first_signal > length_second_signal:73self.second_signal += [0] * (max_length - length_second_signal)74
75"""76Fills the matrix in the following way assuming 'x' is the signal of length 4
77[
78[x[0], x[3], x[2], x[1]],
79[x[1], x[0], x[3], x[2]],
80[x[2], x[1], x[0], x[3]],
81[x[3], x[2], x[1], x[0]]
82]
83"""
84for i in range(max_length):85rotated_signal = deque(self.second_signal)86rotated_signal.rotate(i)87for j, item in enumerate(rotated_signal):88matrix[i][j] += item89
90# multiply the matrix with the first signal91final_signal = np.matmul(np.transpose(matrix), np.transpose(self.first_signal))92
93# rounding-off to two decimal places94return [round(i, 2) for i in final_signal]95
96
97if __name__ == "__main__":98doctest.testmod()99