Mastering Numpy Conjugate: Tips and Tricks for Optimal Performance

You might have worked with complex numbers, tried to solve conjugates of a complex number, and whatnot! However, are you aware of numpy conjugate in Python? Check out this blog to know more!

About numpy conjugate

About numpy conjugate
numpy conjugate

If you have an array with complex numbers and you wish to obtain the complex conjugate, the conjugate function of numpy is the best approach. It holds a varied number of uses:

  • It can be used for arithmetic operations of complex numbers.
  • It works for filtering the signals.
  • It can be used to find Fourier transforms too.

Syntax of numpy conjugate

The conjugate function works well with complex numbers. You need to pass such a number to the function so that it can show the conjugate.

np.conjugate(number)

Real and imaginary parts of conjugate

A complex number is divided into two parts: real and imaginary. The numpy conjugate function works on the imaginary part of the number, i.e., the part with iota or ‘i’. Thus, the real part stays the same while the imaginary part goes through negation. As an example, consider the given number:

num=1 + 2j
print(np.conjugate(num))

The output will be 1-2j. So, we can conclude that the real part doesn’t go through the changes, but the imaginary part in the conjugated number is negative of the imaginary part in the number given by the user.

Working

To understand the workings of conjugate function, consider the given example. It takes an array of complex numbers and provides their conjugate. The array is passed to the conjugate function as its parameter. It’s an extremely easy function to understand.

import numpy as np
# Create a NumPy array of complex numbers.
array = np.array([1 + 2j, 3 - 4j, 5 + 6j, 7 - 8j])
# Get the complex conjugate of the array.
conjugate_array = np.conjugate(array)
# Print the original array and the conjugate array.
print(array)
print(conjugate_array)

The output will be :

[1.+2.j 3.-4.j 5.+6.j 7.-8.j]
[1.-2.j 3.+4.j 5.-6.j 7.+8.j] 

Conjugate for filtering

As discussed before, the numpy conjugate function can be used to filter the signals also. The example explained below illustrates the process of filtering signals using the numpy conjugate.

First, you have to create an array of numbers that the conjugate function will interpret as a signal array. Then, you need to create 2nd array that will act as a filter for the primary signal. Use the conjugate function to derive the conjugate of the filter arrays. After this, you ought to use the ‘*’ arithmetic operator to multiply the signal with the conjugated filter array. The signal that you have now is filtered. You can use the matplotlib library of Python to have a look at the plot of the filter.

import numpy as np
import matplotlib.pyplot as plt

# Create a NumPy array of real numbers.
signal = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# Create a NumPy array of complex numbers with a magnitude of 1 and a phase of 90 degrees.
filter = np.array([1 + 0j, 0 + 1j])

# Filter the signal using the complex conjugate of the filter.
filtered_signal = signal * np.conjugate(filter)

# Plot the original signal and the filtered signal.
plt.plot(signal, label='Original Signal')
plt.plot(filtered_signal, label='Filtered Signal')
plt.legend()
plt.show()

The new signal will be delayed than the primary signal after Filtering with the conjugate function.

Return type

Numpy conjugate has the same return type as the original array. It doesn’t alter the array contents. It has the same data type too. The given example depicts the same. It displays the data type of both the arrays- before conjugation and after conjugation.

import numpy as np

# Create a NumPy array of complex numbers.
array = np.array([1 + 2j, 3 - 4j, 5 + 6j, 7 - 8j])

# Get the complex conjugates of the elements in the array.
conjugate_array = np.conjugate(array)

# Print the data type of the original array and the conjugate array.
print(array.dtype)
print(conjugate_array.dtype)

So the output will be complex in both cases.

#output
complex128
complex128

Conjugate of numpy matrix

The conjugate function extends to matrices also. It works similarly to the above-mentioned array. Here also, only the imaginary part goes through change. It is negated.

import numpy as np

# Create a NumPy matrix of complex numbers.
matrix = np.matrix([[1 + 2j, 3 - 4j], [5 + 6j, 7 - 8j]])

# Get the complex conjugates of the elements in the matrix.
conjugate_matrix = np.conjugate(matrix)

# Print the original matrix and the conjugate matrix.
print(matrix)
print(conjugate_matrix)

The output will be:

[[1.+2.j 3.-4.j]
 [5.+6.j 7.-8.j]]
[[1.-2.j 3.+4.j]
 [5.-6.j 7.+8.j]]

The preferred dtypes

You may couple this function with a numpy array of any data type. It doesn’t change the input array at all.

numpy conjugate for multiplication

You can multiply the original array with the conjugated array. The given example depicts the same. Other purposes include:

  • Squared magnitude of a complex number
  • The power spectrum of a signal
  • Complex arithmetic operations
import numpy as np

# Create a NumPy array of complex numbers.
array = np.array([1 + 2j, 3 - 4j, 5 + 6j, 7 - 8j])

# Get the complex conjugates of the elements in the array.
conjugate_array = np.conjugate(array)

# Multiply the array by its complex conjugate.
multiplied_array = array * conjugate_array

# Print the multiplied array.
print(multiplied_array)

numpy conjugate for division

NumPy division operator (/) is used to carry out division. Eventually, it results in a similar array after dividing. It helps to calculate the inverse of a complex number, its phase, and complex arithmetic operations.

import numpy as np

# Create a NumPy array of complex numbers.
array = np.array([1 + 2j, 3 - 4j, 5 + 6j, 7 - 8j])

# Get the complex conjugates of the elements in the array.
conjugate_array = np.conjugate(array)

# Divide the array by its complex conjugate.
divided_array = array / conjugate_array

# Print the divided array.
print(divided_array)

#output:
[-0.6       +0.8j        -0.28      -0.96j       -0.18032787+0.98360656j
 -0.13274336-0.99115044j]

Numpy conjugate transpose

You must have heard of the Hermitian transpose in the field of mathematics. This is calculated by first finding the conjugate of the values in the array and, subsequently, doing a transpose of the array with conjugated values. It uses two numpy functions, namely numpy.conj() and numpy.transpose(). As input, you need to provide the matrix with complex numbers.

Have a look at the example given below for an elaborate understanding.

import numpy as np

# Create a NumPy matrix
A = np.array([[1, 2j], [3, 4j]])

# Calculate the conjugate transpose of A
A_H = np.conj(A.T)

# Print the conjugate transpose of A
print(A_H)

Hence, you will get the output as follows:

[[1-3j] [2-4j]]

Numpy conjugate transpose array

It is useful in finding conjugated signals in addition to the inner product of Complex Matrices/ Vectors. Besides this, the unitary matrix can also utilize this concept in order to calculate its inverse. The elements of such an array consist of complex conjugates only. Let’s consider this example that displays the conjugate transpose while finding the inner product of vectors.

import numpy as np

# Create two complex vectors
v1 = np.array([1, 2j])
v2 = np.array([3, 4j])

# Calculate the inner product of the two vectors using the conjugate transpose
inner_product = np.vdot(v1, np.conj(v2))

# Print the inner product
print(inner_product)

The output is : (5+2j)

Numpy conjugate vs conj

Let’s understand the differences between the conjugate and conj functions of numpy with the help of this tabular representation. The conjugate() function of numpy is preferred to the other one. This happens because numpy, overall, has a better computational compatibility.

conj()conjugate()
It is a python function. It is a numpy function specifically.
It does not support broadcasting. It supports broadcasting.
It is comparatively slower. It is faster.
It is mainly used for numpy arrays. It is majorly used for numpy arrays.
Numpy conjugate vs conj

The Performance Boost

In order to get better efficiency with np.conjugate, follow the given steps:

  • Use arrays with np.complex128 as the dtype.
  • Avoid using it on larger arrays. It may lead to no memory optimization.
  • For larger arrays, use np.power().

FAQs

Which function works similarly to np.conjugate()?

arr.conj() works in the same manner.

Conclusion

This article explains the conjugate function of numpy. It elaborates on the usage of this function. Furthermore, it throws light on how one can work with complex numbers besides arrays and matrices with complex numbers by making use of the conjugate function. By all means, this is the best way to find the conjugate of such complex numbers.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments