This page was generated from docs/examples/Parameters/Complex_Parameters.ipynb. Interactive online version: .

# Complex Numbers

QCoDeS natively supports complex numbers via the complex datatypes of numpy.

[1]:
import numpy as np

## Complex-valued parameters

QCoDeS parameters can take complex values. There are two types of complex-valued parameters: scalar-valued parameters and array-valued parameters.

### Scalar-valued parameters

Let us create a complex-valued parameter and set and get values for it. An example that one might encounter in physics is the complex impedance.

For any QCoDeS parameter, it holds that adding input validation is a good idea. Complex parameters are no exception. We therefore use the ComplexNumbers validator with our complex parameter.

[2]:
from qcodes.instrument.parameter import Parameter
from qcodes.utils.validators import ComplexNumbers
[3]:
imp = Parameter(name='imp',
label='Impedance',
unit='Ohm',
initial_value=50+0j,
set_cmd=None,
get_cmd=None,
vals=ComplexNumbers())

The ComplexNumbers validator requires explicitly complex values. floats and ints will not pass.

[4]:
for value in np.array([1, -1, 8.2, np.pi]):
try:
imp(value)
print(f'Succesfully set the parameter to {value}')
except TypeError:
print(f'Sorry, but {value} is not complex')
Sorry, but 1.0 is not complex
Sorry, but -1.0 is not complex
Sorry, but 8.2 is not complex
Sorry, but 3.141592653589793 is not complex

The easiest way to make a scalar value complex is probably by adding 0j to it.

[5]:
for value in np.array([1, -1, 8.2, np.pi]) + 0j:
try:
imp(value)
print(f'Succesfully set the parameter to {value}')
except TypeError:
print(f'Sorry, but {value} is not complex')
Succesfully set the parameter to (1+0j)
Succesfully set the parameter to (-1+0j)
Succesfully set the parameter to (8.2+0j)
Succesfully set the parameter to (3.141592653589793+0j)

### Array-valued parameters

There is no separate complex-valued array validator, since the Arrays validator can be customized to cover any real or complex valued case.

Let’s make a little array to hold some quantum state amplitudes. Let’s pretend to be in a 5-dimensional Hilbert space. Our state parameter should thus hold 5 complex numbers (the state expansion coefficients in some implicit basis).

[6]:
from qcodes.utils.validators import Arrays

The proper validator should accept complex numbers and should reject anything of the wrong shape. Note that we get to decide whether we want to accept “non-strictly complex” data.

[7]:
amps_val_strict = Arrays(shape=(5,), valid_types=(np.complex,))
amps_val_lax = Arrays(shape=(5,), valid_types=(np.complex, np.float, np.int))
/tmp/ipykernel_8117/3366591055.py:1: DeprecationWarning: np.complex is a deprecated alias for the builtin complex. To silence this warning, use complex by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use np.complex128 here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
amps_val_strict = Arrays(shape=(5,), valid_types=(np.complex,))
/tmp/ipykernel_8117/3366591055.py:2: DeprecationWarning: np.complex is a deprecated alias for the builtin complex. To silence this warning, use complex by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use np.complex128 here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
amps_val_lax = Arrays(shape=(5,), valid_types=(np.complex, np.float, np.int))
/tmp/ipykernel_8117/3366591055.py:2: DeprecationWarning: np.float is a deprecated alias for the builtin float. To silence this warning, use float by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use np.float64 here.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
amps_val_lax = Arrays(shape=(5,), valid_types=(np.complex, np.float, np.int))
/tmp/ipykernel_8117/3366591055.py:2: DeprecationWarning: np.int is a deprecated alias for the builtin int. To silence this warning, use int by itself. Doing this will not modify any behavior and is safe. When replacing np.int, you may wish to use e.g. np.int64 or np.int32 to specify the precision. If you wish to review your current use, check the release note link for additional information.
Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations
amps_val_lax = Arrays(shape=(5,), valid_types=(np.complex, np.float, np.int))

The strict validator is strict:

[8]:
try:
amps_val_strict.validate(np.array([1, 2, 3, 4, 5]))
except TypeError:
print('Sorry, but integers are not strictly complex')

try:
amps_val_strict.validate(np.array([1.0, 2.0, 3.0, 4.0, 5.0]))
except TypeError:
print('Sorry, but floats are not strictly complex')
Sorry, but integers are not strictly complex
Sorry, but floats are not strictly complex

But note, that the presence of a single imaginary part will cast the whole array as complex:

[9]:
my_array = np.array([1.0 + 0j, 2.0, 3.0, 4.0, 5.0])
print(my_array)
print(my_array.dtype)
amps_val_strict.validate(np.array([1.0 + 0j, 2.0, 3.0, 4.0, 5.0]))
print('Yeah, those are complex numbers')
[1.+0.j 2.+0.j 3.+0.j 4.+0.j 5.+0.j]
complex128
Yeah, those are complex numbers

The lax validator let’s everything through:

[10]:
amps_val_lax.validate(np.array([1, 2, 3, 4, 5]))
amps_val_lax.validate(np.array([1.0, 2.0, 3.0, 4.0, 5.0]))
amps_val_lax.validate(np.array([1.0 + 0j, 2, 3, 4, 5]))

We can use either validator for the parameter.

[11]:
amplitudes = Parameter(name='amplitudes',
label='Amplitudes',
unit='',
set_cmd=None,
get_cmd=None,
vals=amps_val_strict,
initial_value=(1/np.sqrt(2)*np.array([1+1j, 0, 0, 0, 0])))
[12]:
amplitudes()
[12]:
array([0.70710678+0.70710678j, 0.        +0.j        ,
0.        +0.j        , 0.        +0.j        ,
0.        +0.j        ])
[13]:
amplitudes(1/np.sqrt(2)*np.array([0, 1+1j, 0, 0, 0]))
[ ]: