Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeyError raised when simulation with realistic noise #6607

Closed
cosenal opened this issue May 17, 2024 · 4 comments
Closed

KeyError raised when simulation with realistic noise #6607

cosenal opened this issue May 17, 2024 · 4 comments
Labels
kind/bug-report Something doesn't seem to work.

Comments

@cosenal
Copy link

cosenal commented May 17, 2024

Description of the issue

I wanted to use the noise model described in https://quantumai.google/cirq/simulate/noisy_simulation#simulation_with_realistic_noise in the simulation of a very simple circuit (one C-Z gate, nothing else), but it throws a KeyError (see traceback below).

How to reproduce the issue

import cirq, cirq_google

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(cirq.CZ.on(q0, q1))

processor_id = "rainbow"
cal = cirq_google.engine.load_median_device_calibration(processor_id)
noise_props = cirq_google.noise_properties_from_calibration(cal)
noise_model = cirq_google.NoiseModelFromGoogleNoiseProperties(noise_props)

cirq.DensityMatrixSimulator(noise=noise_model).simulate(circuit).final_density_matrix[0, 0].real

The same snippet works if I set noise=None, or if the circuit has a CNOT instead of a CZ gate.

Traceback:

--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Cell In[10], [line 1](vscode-notebook-cell:?execution_count=10&line=1) ----> [1](vscode-notebook-cell:?execution_count=10&line=1) cirq.DensityMatrixSimulator(noise=noise_model).simulate(circuit).final_density_matrix[0, 0].real

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/sim/simulator.py:496, in SimulatesFinalState.simulate(self, program, param_resolver, qubit_order, initial_state)
471 def simulate(
472 self,
473 program: 'cirq.AbstractCircuit',
(...)
476 initial_state: Any = None,
477 ) -> TSimulationTrialResult:
478 """Simulates the supplied Circuit.
479
480 This method returns a result which allows access to the entire
(...)
494 SimulationTrialResults for the simulation. Includes the final state.
495 """
--> 496 return self.simulate_sweep(
497 program, study.ParamResolver(param_resolver), qubit_order, initial_state
498 )[0]

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/sim/simulator.py:511, in SimulatesFinalState.simulate_sweep(self, program, params, qubit_order, initial_state)
500 def simulate_sweep(
501 self,
502 program: 'cirq.AbstractCircuit',
(...)
505 initial_state: Any = None,
506 ) -> List[TSimulationTrialResult]:
507 """Wraps computed states in a list.
508
509 Prefer overriding simulate_sweep_iter.
510 """
--> 511 return list(self.simulate_sweep_iter(program, params, qubit_order, initial_state))

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/sim/simulator_base.py:328, in SimulatorBase.simulate_sweep_iter(self, program, params, qubit_order, initial_state)
322 prefix, suffix = (
323 split_into_matching_protocol_then_general(program, sweep_prefixable)
324 if self._can_be_in_run_prefix(self.noise)
325 else (program[0:0], program)
326 )
327 step_result = None
--> 328 for step_result in self._core_iterator(circuit=prefix, sim_state=sim_state):
329 pass
330 sim_state = step_result._sim_state

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/sim/simulator_base.py:206, in SimulatorBase._core_iterator(self, circuit, sim_state, all_measurements_are_terminal)
203 yield self._create_step_result(sim_state)
204 return
--> 206 noisy_moments = self.noise.noisy_moments(circuit, sorted(circuit.all_qubits()))
207 measured: Dict[Tuple['cirq.Qid', ...], bool] = collections.defaultdict(bool)
208 for moment in noisy_moments:

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/devices/noise_properties.py:111, in NoiseModelFromNoiseProperties.noisy_moments(self, moments, system_qubits)
109 noisy_circuit = split_measure_circuit.copy()
110 for model in self.noise_models:
--> 111 noisy_circuit = noisy_circuit.with_noise(model)
113 # Recombine measurements.
114 final_moments = []

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/circuits/circuit.py:2463, in Circuit.with_noise(self, noise)
2461 qubits = sorted(self.all_qubits())
2462 c_noisy = Circuit()
-> 2463 for op_tree in noise_model.noisy_moments(self, qubits):
2464 # Keep moments aligned
2465 c_noisy += Circuit(op_tree)
2466 return c_noisy

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/value/abc_alt.py:137, in ABCMetaImplementAnyOneOf.new..wrap_scope..impl_of_abstract(*args, **kwargs)
136 def impl_of_abstract(*args, **kwargs):
--> 137 return impl(*args, **kwargs)

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/devices/noise_model.py:102, in NoiseModel._noisy_moments_impl_moment(self, moments, system_qubits)
100 result = []
101 for moment in moments:
--> 102 result.append(self.noisy_moment(moment, system_qubits))
103 return result

File /opt/miniconda3/envs/mitiqenv/lib/python3.11/site-packages/cirq/devices/thermal_noise_model.py:278, in ThermalNoiseModel.noisy_moment(self, moment, system_qubits)
276 if self.skip_measurements and protocols.is_measurement(qubit_op):
277 continue
--> 278 rates = self.rate_matrix_GHz[qubit] * moment_ns
279 kraus_ops = _kraus_ops_from_rates(tuple(rates.reshape(-1)), rates.shape)
280 noise_ops.append(ops.KrausChannel(kraus_ops).on(qubit))

KeyError: cirq.LineQubit(0)

Cirq version
1.3.0

@cosenal cosenal added the kind/bug-report Something doesn't seem to work. label May 17, 2024
@NoureldinYosri
Copy link
Collaborator

NoureldinYosri commented May 17, 2024

hi, this is exactly as the error says. the qubits don't exist on the device. the realsitic noise model represent the noise for the device, that's noise is keyed by qubits and qubit pairs. you can list the qubits on the device by calling

>> noise_props.qubits
[cirq.GridQubit(3, 2),
 cirq.GridQubit(4, 1),
 cirq.GridQubit(4, 2),
 cirq.GridQubit(4, 3),
 cirq.GridQubit(5, 0),
 cirq.GridQubit(5, 1),
 cirq.GridQubit(5, 2),
 cirq.GridQubit(5, 3),
 cirq.GridQubit(5, 4),
 cirq.GridQubit(6, 1),
 cirq.GridQubit(6, 2),
 cirq.GridQubit(6, 3),
 cirq.GridQubit(6, 4),
 cirq.GridQubit(6, 5),
 cirq.GridQubit(7, 2),
 cirq.GridQubit(7, 3),
 cirq.GridQubit(7, 4),
 cirq.GridQubit(7, 5),
 cirq.GridQubit(7, 6),
 cirq.GridQubit(8, 3),
 cirq.GridQubit(8, 4),
 cirq.GridQubit(8, 5),
 cirq.GridQubit(9, 4)]

for example I reran you circuit using cirq.GridQubit(4, 1), cirq.GridQubit(4, 2) which exist on the device

>> q0, q1 = cirq.q(4, 1), cirq.q(4, 2)
>> circuit = cirq.Circuit(cirq.CZ.on(q0, q1))
>> cirq.DensityMatrixSimulator(noise=noise_model).simulate(circuit)
measurements: (no measurements)

qubits: (cirq.GridQubit(4, 1), cirq.GridQubit(4, 2))
final density matrix:
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]

phase:
final density matrix:
[[1.+0.j]]

you may also want to call noise_props.expected_gates() to see which gates are supported by the device and if your circuit contains an unsupported gate then you can compile your circuit to the target gateset using cirq.optimize_for_target_gateset

@cosenal
Copy link
Author

cosenal commented May 18, 2024

@NoureldinYosri Thanks for your reply.

this is exactly as the error says. the qubits don't exist on the device.

This doesn't explain why on the same device I can connect the same qubits with a CNOT gate (as opposed to a CZ), i.e., the following snippet works just fine 🤔

...
q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(cirq.CNOT.on(q0, q1))
...

And in fact, CNOT (CXPowGate) doesn't even show up in the list from noise_props.expected_gates() 🤔

@NoureldinYosri
Copy link
Collaborator

@cosenal CNOT is not a native gate on the device (but CZ is) so the simulator doesn't apply any noise to it (so it doesn't lookup the noise). notice how the result of the simulation is perfect without any noise.

from noise_props.expected_gates() we see that one of the native gatesets on the device is CZGateset so the correct way to run the noisy simulation would be to compile the circuit to that gateset (or another supported gateset)

>> q0, q1 = cirq.LineQubit.range(2)
>> circuit = cirq.Circuit(cirq.CX.on(q0, q1))
>> compiled_circuit = cirq.optimize_for_target_gateset(circuit, gateset=cirq.CZTargetGateset())
>> cirq.DensityMatrixSimulator(noise=noise_model).simulate(compiled_circuit)
KeyError: cirq.LineQubit(0)

Which gives the error as expected since now the simulator actually tries to add the noise and fails because the qubit is not present on the device, if instead we use qubits on the device we get the correct execution

>> q0, q1 = cirq.q(4, 1), cirq.q(4, 2)
>> circuit = cirq.Circuit(cirq.CX.on(q0, q1))
>> compiled_circuit = cirq.optimize_for_target_gateset(circuit, gateset=cirq.CZTargetGateset())
>> cirq.DensityMatrixSimulator(noise=noise_model).simulate(compiled_circuit)
measurements: (no measurements)

qubits: (cirq.GridQubit(4, 1), cirq.GridQubit(4, 2))
final density matrix:
[[ 9.9393892e-01+0.j -1.7796451e-03+0.j  0.0000000e+00+0.j
   0.0000000e+00+0.j]
 [-1.7796451e-03+0.j  4.6467967e-03+0.j  0.0000000e+00+0.j
   0.0000000e+00+0.j]
 [ 0.0000000e+00+0.j  0.0000000e+00+0.j  1.4076923e-03+0.j
  -2.5204695e-06+0.j]
 [ 0.0000000e+00+0.j  0.0000000e+00+0.j -2.5204695e-06+0.j
   6.5811464e-06+0.j]]

phase:
final density matrix:
[[1.+0.j]]

notice that in the ideal simulation (i.e. without noise) we expect to get density matrix with all zeros except at [0, 0], but in this noisy simulation we get a 0.99 at [0, 0] and small values at other entries.


I created #6608 to raise an error when trying to run simulations with qubits not on the device or a circuit not compiled to a supported gateset.

@cosenal
Copy link
Author

cosenal commented May 21, 2024

All clear now! Thanks, @NoureldinYosri

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug-report Something doesn't seem to work.
Projects
None yet
Development

No branches or pull requests

2 participants