qiboteam / qibolab

Quantum hardware module and drivers for Qibo.
https://qibo.science
Apache License 2.0
43 stars 16 forks source link

Unable to play custom pulses with QM #1100

Closed andrea-pasquale closed 2 weeks ago

andrea-pasquale commented 2 weeks ago

The following code is failing using main.

import numpy as np
from qibolab import create_platform, Custom, Pulse, PulseSequence

platform = create_platform("qw11q")

sequence = PulseSequence()

drive_channel = platform.qubits["D1"].drive
duration = 40
pulse = Pulse(amplitude=0.01,
              duration=duration,
              envelope=Custom(i_=np.ones(duration), q_=np.zeros(duration)))
sequence.append((drive_channel, pulse))

sequence |= platform.natives.single_qubit["D1"].MZ()

platform.connect()
result = platform.execute([sequence])
platform.disconnect()
Here is the error.
```py 2024-11-14 14:12:34,561 - qm - INFO - Starting session: 31c229f4-6d22-4c91-baec-345506575398 2024-11-14 14:12:36,796 - qm - INFO - Octave "octave5" Health check passed, current temperature 59 2024-11-14 14:12:37,530 - qm - INFO - Octave "octave6" Health check passed, current temperature 58 2024-11-14 14:12:37,530 - qm - INFO - Performing health check 2024-11-14 14:12:37,550 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con1. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,550 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con2. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con3. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con4. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con5. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con6. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con7. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con8. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - WARNING - Health check warning: Inter-OPX connectivity issues in OPX: con9. Missing ports are: 12, 11, 10, 9. See QM-App for more info. 2024-11-14 14:12:37,551 - qm - INFO - Health check passed Connected to: Rohde&Schwarz SGS100A (serial:1416.0505k02/114164, firmware:4.2.76.0-4.30.046.295) in 0.16s Traceback (most recent call last): File "/nfs/users/andrea.pasquale/qibocal/test_qm.py", line 17, in result = platform.execute([sequence]) File "/nfs/users/andrea.pasquale/qibolab/src/qibolab/_core/platform/platform.py", line 290, in execute results |= self._execute(b, options, configs, sweepers) File "/nfs/users/andrea.pasquale/qibolab/src/qibolab/_core/platform/platform.py", line 224, in _execute new_result = instrument.play(configs, sequences, options, sweepers) File "/nfs/users/andrea.pasquale/qibolab/src/qibolab/_core/instruments/qm/controller.py", line 493, in play self.register_pulses(configs, sequence) File "/nfs/users/andrea.pasquale/qibolab/src/qibolab/_core/instruments/qm/controller.py", line 342, in register_pulses self.register_pulse(id, configs[id], pulse) File "/nfs/users/andrea.pasquale/qibolab/src/qibolab/_core/instruments/qm/controller.py", line 322, in register_pulse return self.config.register_iq_pulse(channel, pulse, max_voltage) File "/nfs/users/andrea.pasquale/qibolab/src/qibolab/_core/instruments/qm/config/config.py", line 158, in register_iq_pulse op = operation(pulse) File "/nfs/users/andrea.pasquale/qibolab/src/qibolab/_core/instruments/qm/config/pulses.py", line 25, in operation return str(hash(pulse)) File "/nfs/users/andrea.pasquale/default/lib/python3.10/site-packages/pydantic/_internal/_model_construction.py", line 446, in hash_func return hash(getter(self.__dict__)) File "/nfs/users/andrea.pasquale/default/lib/python3.10/site-packages/pydantic/_internal/_model_construction.py", line 446, in hash_func return hash(getter(self.__dict__)) TypeError: unhashable type: 'numpy.ndarray' srun: error: fahid: task 0: Exited with exit code 1 ```

I am guessing that the error might be caused by the fact that Custom accepts arrays which qm doesn't seems to like arrays when playing with custom pulses. Any ideas @alecandido @stavros11?

alecandido commented 2 weeks ago

I am guessing that the error might be caused by the fact that Custom accepts arrays which qm doesn't seems to like arrays when playing with custom pulses.

Nope, it's just our fault, not really QM related...

We need to name pulses for the upload, almost in every driver (actually, in all of them, ttbomk). Naming automatically is not completely trivial, and there are two main options:

  1. assigning them a serial
  2. make them content dependent (hashing)

Number 1. is cumbersome, since you need to always have access to a unique container, and grow it. Moreover, the second option is coming with the additional benefit of automatically deduplicating what we are uploading to the instrument (since identical pulses will have identical hashes).

Unfortunately, NumPy arrays are unhashable by default, since they are mutable (thus unsuitable for places where hashes are typically used, e.g. dict keys). But Custom is the only envelope which is parametrized by an entire array. And that's where the problem is being generated.

What we can do is to manually define the __hash__ of the Custom envelope, by hashing the data buffer of the NumPy array, instead of attempting to hash the entire Python object (which will correctly refuse to do it, generating the reported error).

andrea-pasquale commented 2 weeks ago

Since there is already an indentier for pulses in id, we could also just make qm use that instead of referring to its hash, no?

andrea-pasquale commented 2 weeks ago

After discussing offline, we've decided to fix the issue in the following way #1101

What we can do is to manually define the __hash__ of the Custom envelope, by hashing the data buffer of the NumPy array, instead of attempting to hash the entire Python object (which will correctly refuse to do it, generating the reported error).

Using the pulse id doesn't work because it will duplicate the waveform for each pulse with the same waveform.