Skip to content

Commit

Permalink
Remove use of .device in contrib. (quantumlib#4821)
Browse files Browse the repository at this point in the history
Another sub-component for quantumlib#4744 . This removes the use of `circuit.device` from all contrib modules.

BREAKING_CHANGE=removing the `device` property from the `SwapNetwork` class.
It also removes some type checking done by the code (all logic in the bulk still works), which makes it more forgiving.

With the amount of meaningful maintenance contrib has had (not much), I'm not a huge fan of going through a deprecation process for these mild behavior widenings with no API changes. Are others alright with this ?
  • Loading branch information
MichaelBroughton committed Jan 22, 2022
1 parent 7829d67 commit 14097f0
Show file tree
Hide file tree
Showing 18 changed files with 21 additions and 83 deletions.
6 changes: 0 additions & 6 deletions cirq-core/cirq/contrib/acquaintance/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,9 @@ def validate_operation(self, operation: 'cirq.Operation') -> None:
)


def is_acquaintance_strategy(circuit: 'cirq.Circuit') -> bool:
return isinstance(circuit._device, AcquaintanceDevice)


def get_acquaintance_size(obj: Union[circuits.Circuit, ops.Operation]) -> int:
"""The maximum number of qubits to be acquainted with each other."""
if isinstance(obj, circuits.Circuit):
if not is_acquaintance_strategy(obj):
raise TypeError('not is_acquaintance_strategy(circuit)')
return max(tuple(get_acquaintance_size(op) for op in obj.all_operations()) or (0,))
if not isinstance(obj, ops.Operation):
raise TypeError('not isinstance(obj, (Circuit, Operation))')
Expand Down
11 changes: 0 additions & 11 deletions cirq-core/cirq/contrib/acquaintance/devices_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,3 @@ def test_acquaintance_device():
swap_network = cca.SwapNetworkGate((1, 2, 1))
cca.UnconstrainedAcquaintanceDevice.validate_operation(cca.acquaint(*qubits[:2]))
cca.UnconstrainedAcquaintanceDevice.validate_operation(swap_network(*qubits))


def test_get_acquaintance_size():
with pytest.raises(TypeError):
cca.get_acquaintance_size(cirq.Circuit())

with pytest.raises(TypeError):
cca.get_acquaintance_size(3)

circuit = cirq.Circuit(device=cca.UnconstrainedAcquaintanceDevice)
cca.get_acquaintance_size(circuit)
4 changes: 0 additions & 4 deletions cirq-core/cirq/contrib/acquaintance/executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from cirq import circuits, devices, ops, protocols

from cirq.contrib.acquaintance.gates import AcquaintanceOpportunityGate
from cirq.contrib.acquaintance.devices import is_acquaintance_strategy
from cirq.contrib.acquaintance.permutation import (
PermutationGate,
LogicalIndex,
Expand Down Expand Up @@ -74,10 +73,7 @@ def __init__(self, execution_strategy: ExecutionStrategy) -> None:
self.mapping = execution_strategy.initial_mapping.copy()

def __call__(self, strategy: 'cirq.Circuit'):
if not is_acquaintance_strategy(strategy):
raise TypeError('not is_acquaintance_strategy(strategy)')
expose_acquaintance_gates(strategy)
strategy.device = self.execution_strategy.device
super().optimize_circuit(strategy)
return self.mapping.copy()

Expand Down
3 changes: 0 additions & 3 deletions cirq-core/cirq/contrib/acquaintance/executor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@ def test_executor_explicit():
bad_gates = {(0,): ExampleGate(['0']), (0, 1): ExampleGate(['0', '1'])}
cca.GreedyExecutionStrategy(bad_gates, initial_mapping)

with pytest.raises(TypeError):
executor(cirq.Circuit())

with pytest.raises(TypeError):
bad_strategy = cirq.Circuit(cirq.X(qubits[0]))
executor(bad_strategy)
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/contrib/acquaintance/gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def test_acquaint_part_pairs(part_lens):
n_qubits += part_len
qubits = cirq.LineQubit.range(n_qubits)
swap_network_op = cca.SwapNetworkGate(part_lens, acquaintance_size=None)(*qubits)
swap_network = cirq.Circuit(swap_network_op, device=cca.UnconstrainedAcquaintanceDevice)
swap_network = cirq.Circuit(swap_network_op)
initial_mapping = {q: i for i, q in enumerate(qubits)}

actual_opps = cca.get_logical_acquaintance_opportunities(swap_network, initial_mapping)
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/contrib/acquaintance/inspection_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def get_acquaintance_dag(strategy: 'cirq.Circuit', initial_mapping: LogicalMappi
for op in moment.operations
if isinstance(op, AcquaintanceOperation)
)
return circuits.CircuitDag.from_ops(acquaintance_ops, device=strategy.device)
return circuits.CircuitDag.from_ops(acquaintance_ops)


def get_logical_acquaintance_opportunities(
Expand Down
10 changes: 1 addition & 9 deletions cirq-core/cirq/contrib/acquaintance/mutation_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from cirq import circuits, ops, optimizers

from cirq.contrib.acquaintance.gates import SwapNetworkGate, AcquaintanceOpportunityGate
from cirq.contrib.acquaintance.devices import is_acquaintance_strategy, get_acquaintance_size
from cirq.contrib.acquaintance.devices import get_acquaintance_size
from cirq.contrib.acquaintance.permutation import PermutationGate

if TYPE_CHECKING:
Expand All @@ -41,10 +41,6 @@ def rectify_acquaintance_strategy(circuit: 'cirq.Circuit', acquaint_first: bool
Raises:
TypeError: If the circuit is not an acquaintance strategy.
"""

if not is_acquaintance_strategy(circuit):
raise TypeError('not is_acquaintance_strategy(circuit)')

rectified_moments = []
for moment in circuit:
gate_type_to_ops: Dict[bool, List[ops.GateOperation]] = collections.defaultdict(list)
Expand Down Expand Up @@ -85,10 +81,6 @@ def replace_acquaintance_with_swap_network(
Raises:
TypeError: circuit is not an acquaintance strategy.
"""

if not is_acquaintance_strategy(circuit):
raise TypeError('not is_acquaintance_strategy(circuit)')

rectify_acquaintance_strategy(circuit)
reflected = False
reverse_map = {q: r for q, r in zip(qubit_order, reversed(qubit_order))}
Expand Down
13 changes: 2 additions & 11 deletions cirq-core/cirq/contrib/acquaintance/mutation_utils_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,6 @@ def test_complete_acquaintance_strategy():
def test_rectification():
qubits = cirq.LineQubit.range(4)

with pytest.raises(TypeError):
cca.rectify_acquaintance_strategy(cirq.Circuit())

perm_gate = cca.SwapPermutationGate()
operations = [
perm_gate(*qubits[:2]),
Expand All @@ -153,7 +150,7 @@ def test_rectification():
perm_gate(*qubits[2:]),
]

strategy = cirq.Circuit(operations, device=cca.UnconstrainedAcquaintanceDevice)
strategy = cirq.Circuit(operations)
cca.rectify_acquaintance_strategy(strategy)
actual_text_diagram = strategy.to_text_diagram().strip()
expected_text_diagram = """
Expand All @@ -167,7 +164,7 @@ def test_rectification():
""".strip()
assert actual_text_diagram == expected_text_diagram

strategy = cirq.Circuit(operations, device=cca.UnconstrainedAcquaintanceDevice)
strategy = cirq.Circuit(operations)
cca.rectify_acquaintance_strategy(strategy, False)
actual_text_diagram = strategy.to_text_diagram()
expected_text_diagram = """
Expand All @@ -180,9 +177,3 @@ def test_rectification():
3: ─────────█───────1↦0───
""".strip()
assert actual_text_diagram == expected_text_diagram


def test_replace_acquaintance_with_swap_network():
with pytest.raises(TypeError):
qubits = cirq.LineQubit.range(3)
cca.replace_acquaintance_with_swap_network(cirq.Circuit(), qubits)
3 changes: 0 additions & 3 deletions cirq-core/cirq/contrib/acquaintance/optimizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from cirq import ops

from cirq.contrib.acquaintance.devices import is_acquaintance_strategy
from cirq.contrib.acquaintance.gates import acquaint
from cirq.contrib.acquaintance.executor import AcquaintanceOperation
from cirq.contrib.acquaintance.mutation_utils import expose_acquaintance_gates
Expand All @@ -28,8 +27,6 @@

def remove_redundant_acquaintance_opportunities(strategy: 'cirq.Circuit') -> int:
"""Removes redundant acquaintance opportunities."""
if not is_acquaintance_strategy(strategy):
raise TypeError('not is_acquaintance_strategy(circuit)')

qubits = sorted(strategy.all_qubits())
mapping = {q: i for i, q in enumerate(qubits)}
Expand Down
13 changes: 2 additions & 11 deletions cirq-core/cirq/contrib/acquaintance/optimizers_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,17 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import pytest

import cirq
import cirq.testing as ct
import cirq.contrib.acquaintance as cca


def test_remove_redundant_acquaintance_opportunities():
device = cca.UnconstrainedAcquaintanceDevice
a, b, c, d, e = cirq.LineQubit.range(5)
swap = cca.SwapPermutationGate()

with pytest.raises(TypeError):
ops = [cca.acquaint(a, b)]
strategy = cirq.Circuit(ops)
cca.remove_redundant_acquaintance_opportunities(strategy)

ops = [cca.acquaint(a, b), cca.acquaint(a, b)]
strategy = cirq.Circuit(ops, device=device)
strategy = cirq.Circuit(ops)
diagram_before = """
0: ───█───█───
│ │
Expand All @@ -47,7 +38,7 @@ def test_remove_redundant_acquaintance_opportunities():
ct.assert_has_diagram(strategy, diagram_after)

ops = [cca.acquaint(a, b), cca.acquaint(c, d), swap(d, e), swap(c, d), cca.acquaint(d, e)]
strategy = cirq.Circuit(ops, device=device)
strategy = cirq.Circuit(ops)
diagram_before = """
0: ───█───────────────────
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_shift_swap_network_gate_acquaintance_opps(left_part_lens, right_part_le
gate = cca.ShiftSwapNetworkGate(left_part_lens, right_part_lens)
n_qubits = gate.qubit_count()
qubits = cirq.LineQubit.range(n_qubits)
strategy = cirq.Circuit(gate(*qubits), device=cca.UnconstrainedAcquaintanceDevice)
strategy = cirq.Circuit(gate(*qubits))

# actual_opps
initial_mapping = {q: i for i, q in enumerate(qubits)}
Expand Down
11 changes: 4 additions & 7 deletions cirq-core/cirq/contrib/acquaintance/strategies/complete.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

from cirq import circuits, ops

from cirq.contrib.acquaintance.devices import UnconstrainedAcquaintanceDevice
from cirq.contrib.acquaintance.gates import acquaint
from cirq.contrib.acquaintance.mutation_utils import (
expose_acquaintance_gates,
Expand Down Expand Up @@ -47,16 +46,14 @@ def complete_acquaintance_strategy(
if acquaintance_size < 0:
raise ValueError('acquaintance_size must be non-negative.')
if acquaintance_size == 0:
return circuits.Circuit(device=UnconstrainedAcquaintanceDevice)
return circuits.Circuit()

if acquaintance_size > len(qubit_order):
return circuits.Circuit(device=UnconstrainedAcquaintanceDevice)
return circuits.Circuit()
if acquaintance_size == len(qubit_order):
return circuits.Circuit(acquaint(*qubit_order), device=UnconstrainedAcquaintanceDevice)
return circuits.Circuit(acquaint(*qubit_order))

strategy = circuits.Circuit(
(acquaint(q) for q in qubit_order), device=UnconstrainedAcquaintanceDevice
)
strategy = circuits.Circuit((acquaint(q) for q in qubit_order))
for size_to_acquaint in range(2, acquaintance_size + 1):
expose_acquaintance_gates(strategy)
replace_acquaintance_with_swap_network(strategy, qubit_order, size_to_acquaint, swap_gate)
Expand Down
3 changes: 1 addition & 2 deletions cirq-core/cirq/contrib/acquaintance/strategies/cubic.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from typing import Iterable, Sequence, Tuple, TypeVar, TYPE_CHECKING

from cirq import circuits, ops
from cirq.contrib.acquaintance.devices import UnconstrainedAcquaintanceDevice
from cirq.contrib.acquaintance.gates import acquaint
from cirq.contrib.acquaintance.permutation import LinearPermutationGate, SwapPermutationGate

Expand Down Expand Up @@ -77,4 +76,4 @@ def cubic_acquaintance_strategy(
)
moments.append(moment)
index_order = new_index_order[::-1]
return circuits.Circuit(moments, device=UnconstrainedAcquaintanceDevice)
return circuits.Circuit(moments)
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from typing import cast, Iterable, List, Sequence, Tuple, TYPE_CHECKING

from cirq import circuits, ops
from cirq.contrib.acquaintance.devices import UnconstrainedAcquaintanceDevice
from cirq.contrib.acquaintance.gates import acquaint, SwapNetworkGate
from cirq.contrib.acquaintance.mutation_utils import expose_acquaintance_gates

Expand Down Expand Up @@ -61,7 +60,7 @@ def quartic_paired_acquaintance_strategy(
qubits = qubit_pairs_to_qubit_order(qubit_pairs)
n_qubits = len(qubits)
swap_network = SwapNetworkGate((1,) * n_qubits, 2)(*qubits)
strategy = circuits.Circuit(swap_network, device=UnconstrainedAcquaintanceDevice)
strategy = circuits.Circuit(swap_network)
expose_acquaintance_gates(strategy)
for i in reversed(range(0, n_qubits, 2)):
moment = ops.Moment([acquaint(*qubits[j : j + 4]) for j in range(i % 4, n_qubits - 3, 4)])
Expand Down
4 changes: 1 addition & 3 deletions cirq-core/cirq/contrib/paulistring/recombine.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,4 @@ def move_pauli_strings_into_circuit(

assert not string_dag.nodes(), 'There was a cycle in the CircuitDag'

return circuits.Circuit(
output_ops, strategy=circuits.InsertStrategy.EARLIEST, device=circuit_right.device
)
return circuits.Circuit(output_ops, strategy=circuits.InsertStrategy.EARLIEST)
4 changes: 1 addition & 3 deletions cirq-core/cirq/contrib/routing/greedy.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ def route_circuit_greedily(
router.route()

swap_network = router.swap_network
swap_network.circuit = circuits.Circuit(
swap_network.circuit.all_operations(), device=swap_network.device
)
swap_network.circuit = circuits.Circuit(swap_network.circuit.all_operations())
return swap_network


Expand Down
8 changes: 3 additions & 5 deletions cirq-core/cirq/contrib/routing/swap_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ class SwapNetwork:
"""

def __init__(
self, circuit: 'cirq.Circuit', initial_mapping: Dict['cirq.Qid', 'cirq.Qid']
self,
circuit: 'cirq.Circuit',
initial_mapping: Dict['cirq.Qid', 'cirq.Qid'],
) -> None:
if not all(isinstance(i, ops.Qid) for I in initial_mapping.items() for i in I):
raise ValueError('Mapping must be from Qids to Qids.')
Expand All @@ -56,10 +58,6 @@ def __eq__(self, other) -> bool:
return NotImplemented
return self.circuit == other.circuit and self.initial_mapping == other.initial_mapping

@property
def device(self) -> 'cirq.Device':
return self.circuit.device

def __str__(self) -> str:
circuit = self.circuit.copy()
cca.display_mapping(circuit, self.initial_mapping)
Expand Down
2 changes: 2 additions & 0 deletions cirq-core/cirq/protocols/qasm.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ def qasm(
kwargs['args'] = args
if qubits is not None:
kwargs['qubits'] = tuple(qubits)
# pylint: disable=not-callable
result = method(**kwargs)
# pylint: enable=not-callable
if result is not None and result is not NotImplemented:
return result

Expand Down

0 comments on commit 14097f0

Please sign in to comment.