Cirq icon indicating copy to clipboard operation
Cirq copied to clipboard

docs/hardware/pasqal/getting_started.ipynb fails to execute in Google Colab

Open pavoljuhas opened this issue 1 year ago • 3 comments

Description of the issue

The cirq-pasqal getting_started.ipynb notebook calls cirq.optimize_for_target_gateset which should produce a circuit that validates w/r to pasqal device, but this fails when run on https://colab.research.google.com/ notebook.

The same notebook passes if run on a local Debian Linux OS. This seems to be cause by different round-off errors of the CPUs, which lead to differing optimized circuits.

The root cause appears to be that cirq.optimize_for_target_gateset does not ensure that for PasqalGateset the new circuit has single-operation moments, they just happen to be so for getting_started.ipynb with a favorable round-off errors. The optimization may also produce a moment with 2 operations, which fails validation as follows:

How to reproduce the issue

Create and run fresh colab at https://colab.research.google.com

# cell 1
!pip install "cirq_pasqal==1.4.1"

# cell 2
import cirq
import cirq_pasqal
from cirq_pasqal import TwoDQubit, PasqalVirtualDevice

p_qubits = TwoDQubit.square(6)  # 6x6 square array of TwoDQubits

# Initialize and create a circuit
initial_circuit = cirq.Circuit()
initial_circuit.append(cirq.CZ(p_qubits[0], p_qubits[1]))
initial_circuit.append(cirq.Z(p_qubits[0]))
initial_circuit.append(cirq.CX(p_qubits[0], p_qubits[2]))

# Create a Pasqal device with a control radius of 2.1 (in units of the lattice spacing)
p_device = PasqalVirtualDevice(control_radius=2.1, qubits=p_qubits)
pasqal_gateset = cirq_pasqal.PasqalGateset(include_additional_controlled_ops=False)

print("INITIAL\n")
print(initial_circuit)
print()

pasqal_circuit = cirq.optimize_for_target_gateset(
    initial_circuit, gateset=pasqal_gateset
)
print("OPTIMIZED\n")
print(pasqal_circuit)

print("\nVALIDATION\n")
p_device.validate_circuit(pasqal_circuit)
INITIAL

(0, 0): ───@───Z───@─── │ │ (1, 0): ───@───────┼─── │ (2, 0): ───────────X───

OPTIMIZED

(0, 0): ───@───Z──────────────────@───Z───────────────────── │ │ (1, 0): ───@──────────────────────┼───────────────────────── │ (2, 0): ───────────PhX(0.5)^0.5───@───PhX(-0.5)^0.5───Z^0───

VALIDATION


ValueError Traceback (most recent call last) in <cell line: 28>() 26 27 print("\nVALIDATION\n") ---> 28 p_device.validate_circuit(pasqal_circuit)

2 frames /usr/local/lib/python3.10/dist-packages/cirq_pasqal/pasqal_device.py in validate_circuit(self, circuit) 137 ValueError: If the given circuit can't be run on this device 138 """ --> 139 super().validate_circuit(circuit) 140 141 # Measurements must be in the last non-empty moment

/usr/local/lib/python3.10/dist-packages/cirq/devices/device.py in validate_circuit(self, circuit) 84 """ 85 for moment in circuit: ---> 86 self.validate_moment(moment) 87 88 def validate_moment(self, moment: 'cirq.Moment') -> None:

/usr/local/lib/python3.10/dist-packages/cirq_pasqal/pasqal_device.py in validate_moment(self, moment) 233 for operation in moment: 234 if not isinstance(operation.gate, cirq.MeasurementGate): --> 235 raise ValueError("Cannot do simultaneous gates. Use cirq.InsertStrategy.NEW.") 236 237 def minimal_distance(self) -> float:

ValueError: Cannot do simultaneous gates. Use cirq.InsertStrategy.NEW.

Cirq version

1.4.1

pavoljuhas avatar Jun 28 '24 02:06 pavoljuhas

Circq cync: Goal is to enable this notebook again and make sure it works.

dstrain115 avatar Jul 17 '24 17:07 dstrain115

I am trying to understand what happened here:

This code in the main was added in pull request #6656:

# TODO(https://github.com/quantumlib/Cirq/issues/6655) - remove after fixup
pasqal_circuit = cirq.Circuit(pasqal_circuit.all_operations(),
                              strategy=cirq.InsertStrategy.NEW)

It was added as a workaround for the original circuit:

pasqal_circuit = cirq.optimize_for_target_gateset(initial_circuit,
                                                  gateset=pasqal_gateset)

So this issue is still open to address the bug in cirq.optimize_for_target_gateset!

I will be trying to look into cirq.optimize_for_target_gateset and see. "@pavoljuhas please correct me if there is something I am getting wrong."

rogerzmukiibi avatar Oct 02 '24 18:10 rogerzmukiibi

The workaround in #6656 transforms pasqal_circuit so that each moment has exactly one operation. This is ensured by cirq.InsertStrategy.NEW which tells cirq to create new moment for each operation in the phase_circuit.all_operations() sequence. Before that the moment 4 in the initial example would be

In: pasqal_circuit[4]
Out: cirq.Moment(
    cirq.PhasedXPowGate(phase_exponent=-0.5, exponent=0.5).on(pasqal.TwoDQubit(2, 0)),
    (cirq.Z**-1.0).on(pasqal.TwoDQubit(0, 0)),
)

which fails validation for PasqalVirtualDevice, because it requires one operations per moment (excluding measurements) - https://github.com/quantumlib/Cirq/blob/95f6a3f17a723d67927746a62992011be98b78b9/cirq-pasqal/cirq_pasqal/pasqal_device.py#L232-L235

pavoljuhas avatar Oct 03 '24 00:10 pavoljuhas