Skip to content

Commit 07ee32d

Browse files
tonybruguierrht
authored andcommitted
Remove BooleanHamiltonian object (quantumlib#5099)
Now that v0.14 is released, delete deprecate object
1 parent 8473eb8 commit 07ee32d

File tree

9 files changed

+12
-130
lines changed

9 files changed

+12
-130
lines changed

cirq-core/cirq/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,6 @@
196196
BaseDensePauliString,
197197
bit_flip,
198198
BitFlipChannel,
199-
BooleanHamiltonian,
200199
BooleanHamiltonianGate,
201200
CCX,
202201
CCXPowGate,

cirq-core/cirq/json_resolver_cache.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ def _class_resolver_dictionary() -> Dict[str, ObjectFactory]:
3333
from cirq.experiments import CrossEntropyResult, CrossEntropyResultDict, GridInteractionLayer
3434
from cirq.experiments.grid_parallel_two_qubit_xeb import GridParallelXEBMetadata
3535

36+
def _boolean_hamiltonian_gate_op(qubit_map, boolean_strs, theta):
37+
return cirq.BooleanHamiltonianGate(
38+
parameter_names=list(qubit_map.keys()), boolean_strs=boolean_strs, theta=theta
39+
).on(*qubit_map.values())
40+
3641
def _identity_operation_from_dict(qubits, **kwargs):
3742
return cirq.identity_each(*qubits)
3843

@@ -58,7 +63,6 @@ def _parallel_gate_op(gate, qubits):
5863
'AsymmetricDepolarizingChannel': cirq.AsymmetricDepolarizingChannel,
5964
'BitFlipChannel': cirq.BitFlipChannel,
6065
'BitstringAccumulator': cirq.work.BitstringAccumulator,
61-
'BooleanHamiltonian': cirq.BooleanHamiltonian,
6266
'BooleanHamiltonianGate': cirq.BooleanHamiltonianGate,
6367
'CCNotPowGate': cirq.CCNotPowGate,
6468
'CCXPowGate': cirq.CCXPowGate,
@@ -186,6 +190,7 @@ def _parallel_gate_op(gate, qubits):
186190
'ZPowGate': cirq.ZPowGate,
187191
'ZZPowGate': cirq.ZZPowGate,
188192
# Old types, only supported for backwards-compatibility
193+
'BooleanHamiltonian': _boolean_hamiltonian_gate_op, # Removed in v0.15
189194
'IdentityOperation': _identity_operation_from_dict,
190195
'ParallelGateOperation': _parallel_gate_op, # Removed in v0.14
191196
'SingleQubitMatrixGate': single_qubit_matrix_gate,

cirq-core/cirq/ops/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
)
3232

3333
from cirq.ops.boolean_hamiltonian import (
34-
BooleanHamiltonian,
3534
BooleanHamiltonianGate,
3635
)
3736

cirq-core/cirq/ops/boolean_hamiltonian.py

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -30,106 +30,10 @@
3030

3131
import cirq
3232
from cirq import value
33-
from cirq._compat import deprecated_class
3433
from cirq.ops import raw_types
3534
from cirq.ops.linear_combinations import PauliSum, PauliString
3635

3736

38-
@deprecated_class(deadline='v0.15', fix='Use cirq.BooleanHamiltonianGate')
39-
@value.value_equality
40-
class BooleanHamiltonian(raw_types.Operation):
41-
"""An operation that represents a Hamiltonian from a set of Boolean functions."""
42-
43-
def __init__(
44-
self,
45-
qubit_map: Dict[str, 'cirq.Qid'],
46-
boolean_strs: Sequence[str],
47-
theta: float,
48-
):
49-
"""Builds a BooleanHamiltonian.
50-
51-
For each element of a sequence of Boolean expressions, the code first transforms it into a
52-
polynomial of Pauli Zs that represent that particular expression. Then, we sum all the
53-
polynomials, thus making a function that goes from a series to Boolean inputs to an integer
54-
that is the number of Boolean expressions that are true.
55-
56-
For example, if we were using this gate for the unweighted max-cut problem that is typically
57-
used to demonstrate the QAOA algorithm, there would be one Boolean expression per edge. Each
58-
Boolean expression would be true iff the vertices on that are in different cuts (i.e. it's)
59-
an XOR.
60-
61-
Then, we compute exp(-j * theta * polynomial), which is unitary because the polynomial is
62-
Hermitian.
63-
64-
Args:
65-
boolean_strs: The list of Sympy-parsable Boolean expressions.
66-
qubit_map: map of string (boolean variable name) to qubit.
67-
theta: The evolution time (angle) for the Hamiltonian
68-
69-
Raises:
70-
ValueError: If the any qubits are not 2D.
71-
"""
72-
if any(q.dimension != 2 for q in qubit_map.values()):
73-
raise ValueError('All qubits must be 2-dimensional.')
74-
self._qubit_map: Dict[str, 'cirq.Qid'] = qubit_map
75-
self._boolean_strs: Sequence[str] = boolean_strs
76-
self._theta: float = theta
77-
78-
def with_qubits(self, *new_qubits: 'cirq.Qid') -> 'BooleanHamiltonian':
79-
if len(self._qubit_map) != len(new_qubits):
80-
raise ValueError('Length of replacement qubits must be the same')
81-
new_qubit_map = {
82-
variable_name: new_qubit
83-
for variable_name, new_qubit in zip(self._qubit_map, new_qubits)
84-
}
85-
return BooleanHamiltonian(
86-
new_qubit_map,
87-
self._boolean_strs,
88-
self._theta,
89-
)
90-
91-
@property
92-
def qubits(self) -> Tuple[raw_types.Qid, ...]:
93-
return tuple(self._qubit_map.values())
94-
95-
def num_qubits(self) -> int:
96-
return len(self._qubit_map)
97-
98-
def _value_equality_values_(self):
99-
return self._qubit_map, self._boolean_strs, self._theta
100-
101-
def _json_dict_(self) -> Dict[str, Any]:
102-
return {
103-
'qubit_map': self._qubit_map,
104-
'boolean_strs': self._boolean_strs,
105-
'theta': self._theta,
106-
}
107-
108-
@classmethod
109-
def _from_json_dict_(cls, qubit_map, boolean_strs, theta, **kwargs):
110-
return cls(qubit_map, boolean_strs, theta)
111-
112-
def _decompose_(self):
113-
boolean_exprs = [sympy_parser.parse_expr(boolean_str) for boolean_str in self._boolean_strs]
114-
hamiltonian_polynomial_list = [
115-
PauliSum.from_boolean_expression(boolean_expr, self._qubit_map)
116-
for boolean_expr in boolean_exprs
117-
]
118-
119-
return _get_gates_from_hamiltonians(
120-
hamiltonian_polynomial_list, self._qubit_map, self._theta
121-
)
122-
123-
def _has_unitary_(self):
124-
return True
125-
126-
@property
127-
def gate(self) -> 'cirq.Gate':
128-
return BooleanHamiltonianGate(
129-
tuple(self._qubit_map.keys()), self._boolean_strs, self._theta
130-
)
131-
132-
13337
@value.value_equality
13438
class BooleanHamiltonianGate(raw_types.Gate):
13539
"""A gate that represents a Hamiltonian from a set of Boolean functions."""

cirq-core/cirq/ops/boolean_hamiltonian_test.py

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@
5353
'(x2 | x1) ^ x0',
5454
],
5555
)
56-
@pytest.mark.parametrize('transform', [lambda op: op, lambda op: op.gate.on(*op.qubits)])
57-
def test_circuit(boolean_str, transform):
56+
def test_circuit(boolean_str):
5857
boolean_expr = sympy_parser.parse_expr(boolean_str)
5958
var_names = cirq.parameter_names(boolean_expr)
6059
qubits = [cirq.NamedQubit(name) for name in var_names]
@@ -73,14 +72,13 @@ def test_circuit(boolean_str, transform):
7372
circuit = cirq.Circuit()
7473
circuit.append(cirq.H.on_each(*qubits))
7574

76-
with cirq.testing.assert_deprecated('Use cirq.BooleanHamiltonianGate', deadline='v0.15'):
77-
hamiltonian_gate = cirq.BooleanHamiltonian(
78-
{q.name: q for q in qubits}, [boolean_str], 0.1 * math.pi
79-
)
75+
hamiltonian_gate = cirq.BooleanHamiltonianGate(
76+
{q.name: q for q in qubits}, [boolean_str], 0.1 * math.pi
77+
)
8078

8179
assert hamiltonian_gate.num_qubits() == n
8280

83-
circuit.append(transform(hamiltonian_gate))
81+
circuit.append(hamiltonian_gate.on(*qubits))
8482

8583
phi = cirq.Simulator().simulate(circuit, qubit_order=qubits, initial_state=0).state_vector()
8684
actual = np.arctan2(phi.real, phi.imag) - math.pi / 2.0 > 0.0
@@ -89,28 +87,6 @@ def test_circuit(boolean_str, transform):
8987
np.testing.assert_array_equal(actual, expected)
9088

9189

92-
def test_with_custom_names():
93-
q0, q1, q2, q3 = cirq.LineQubit.range(4)
94-
with cirq.testing.assert_deprecated(
95-
'Use cirq.BooleanHamiltonianGate', deadline='v0.15', count=3
96-
):
97-
original_op = cirq.BooleanHamiltonian(
98-
{'a': q0, 'b': q1},
99-
['a'],
100-
0.1,
101-
)
102-
assert cirq.decompose(original_op) == [cirq.Rz(rads=-0.05).on(q0)]
103-
104-
renamed_op = original_op.with_qubits(q2, q3)
105-
assert cirq.decompose(renamed_op) == [cirq.Rz(rads=-0.05).on(q2)]
106-
107-
with pytest.raises(ValueError, match='Length of replacement qubits must be the same'):
108-
original_op.with_qubits(q2)
109-
110-
with pytest.raises(ValueError, match='All qubits must be 2-dimensional'):
111-
original_op.with_qubits(q0, cirq.LineQid(1, 3))
112-
113-
11490
def test_gate_with_custom_names():
11591
q0, q1, q2, q3 = cirq.LineQubit.range(4)
11692
gate = cirq.BooleanHamiltonianGate(

cirq-core/cirq/protocols/json_test_data/BooleanHamiltonian.repr

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[cirq.BooleanHamiltonianGate(parameter_names=['q0'], boolean_strs=['q0'], theta=0.20160913).on(cirq.NamedQubit('q0'))]

cirq-core/cirq/protocols/json_test_data/spec.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@
190190
],
191191
deprecated={
192192
'GlobalPhaseOperation': 'v0.16',
193-
'BooleanHamiltonian': 'v0.15',
194193
'SymmetricalQidPair': 'v0.15',
195194
},
196195
tested_elsewhere=[

0 commit comments

Comments
 (0)