Skip to content

Commit 9d695c5

Browse files
authored
Fix BooleanHamiltonian.with_qubits() to work with not only NamedQubits (#4396)
The current code at head does not implement BooleanHamiltonian.with_qubits() correctly. It assumes that the qubits are named and then maps them to the variable name. This is restrictive, does not follow the other classes' with_qubits(). It is also incorrect because it silently accepts a list of qubits with missing entries (e.g. there is a variable name 'a' but we don't provide a qubit named 'a'), and the error is thrown only when decompose_once() is called. Instead, here the code accepts a list of qubits and replaces them in the map. It requires that there are as many qubits provided as there were when building the object. Also, it relies on the order of the qubit keys when building the BooleanHamiltonian object, but that is currently a restriction of the API. Fixes #4390.
1 parent 3810349 commit 9d695c5

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

cirq-core/cirq/ops/boolean_hamiltonian.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
[3] https://github.com/rsln-s/IEEE_QW_2020/blob/master/Slides.pdf
2222
"""
2323

24-
from typing import cast, Any, Dict, Generator, List, Sequence, Tuple
24+
from typing import Any, Dict, Generator, List, Sequence, Tuple
2525

2626
import sympy.parsing.sympy_parser as sympy_parser
2727

@@ -66,8 +66,14 @@ def __init__(
6666
self._theta: float = theta
6767

6868
def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'BooleanHamiltonian':
69+
if len(self._qubit_map) != len(new_qubits):
70+
raise ValueError('Length of replacement qubits must be the same')
71+
new_qubit_map = {
72+
variable_name: new_qubit
73+
for variable_name, new_qubit in zip(self._qubit_map, new_qubits)
74+
}
6975
return BooleanHamiltonian(
70-
{cast(cirq.NamedQubit, q).name: q for q in new_qubits},
76+
new_qubit_map,
7177
self._boolean_strs,
7278
self._theta,
7379
)

cirq-core/cirq/ops/boolean_hamiltonian_test.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ def test_circuit(boolean_str):
7272
hamiltonian_gate = cirq.BooleanHamiltonian(
7373
{q.name: q for q in qubits}, [boolean_str], 0.1 * math.pi
7474
)
75-
assert hamiltonian_gate.with_qubits(*qubits) == hamiltonian_gate
7675

7776
assert hamiltonian_gate.num_qubits() == n
7877

@@ -83,3 +82,19 @@ def test_circuit(boolean_str):
8382

8483
# Compare the two:
8584
np.testing.assert_array_equal(actual, expected)
85+
86+
87+
def test_with_custom_names():
88+
q0, q1, q2, q3 = cirq.LineQubit.range(4)
89+
original_op = cirq.BooleanHamiltonian(
90+
{'a': q0, 'b': q1},
91+
['a'],
92+
0.1,
93+
)
94+
assert cirq.decompose(original_op) == [cirq.Rz(rads=-0.05).on(q0)]
95+
96+
renamed_op = original_op.with_qubits(q2, q3)
97+
assert cirq.decompose(renamed_op) == [cirq.Rz(rads=-0.05).on(q2)]
98+
99+
with pytest.raises(ValueError, match='Length of replacement qubits must be the same'):
100+
original_op.with_qubits(q2)

0 commit comments

Comments
 (0)