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

Revert "Allow CircuitOperations in cirq.optimized_for_sycamore" #4356

Merged
merged 1 commit into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ def _is_native_sycamore_op(self, op: cirq.Operation) -> bool:
):
return True

if gate is None and isinstance(op.untagged, cirq.CircuitOperation):
subcircuit = op.untagged.circuit
return all(self._is_native_sycamore_op(op) for op in subcircuit.all_operations())

return False

# TODO(#3388) Add summary line to docstring.
Expand Down Expand Up @@ -135,13 +131,12 @@ def on_stuck_raise(bad):
keep=self._is_native_sycamore_op,
intercepting_decomposer=self._convert_one,
on_stuck_raise=None if self.ignore_failures else on_stuck_raise,
preserve_structure=True, # keep CircuitOps but decompose their contents
)

def optimization_at(
self, circuit: cirq.Circuit, index: int, op: cirq.Operation
) -> Optional[cirq.PointOptimizationSummary]:
if not isinstance(op, (cirq.GateOperation, cirq.CircuitOperation)):
if not isinstance(op, cirq.GateOperation):
return None

gate = op.gate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,52 +78,13 @@ def test_single_qubit_gate_phased_xz():
assert ops[0].gate == gate


def test_circuit_operation_inspection():
q0, q1 = cirq.LineQubit.range(2)
gate = cirq.PhasedXZGate(axis_phase_exponent=0.2, x_exponent=0.3, z_exponent=0.4)
cop = cirq.CircuitOperation(cirq.FrozenCircuit(gate(q0)))
assert cgoc.ConvertToSycamoreGates()._is_native_sycamore_op(cop)

cop2 = cirq.CircuitOperation(cirq.FrozenCircuit(cirq.SWAP(q0, q1)))
assert not cgoc.ConvertToSycamoreGates()._is_native_sycamore_op(cop2)


def test_circuit_operation_conversion():
q0, q1 = cirq.LineQubit.range(2)
subcircuit = cirq.FrozenCircuit(cirq.X(q0), cirq.SWAP(q0, q1))
circuit = cirq.Circuit(cirq.CircuitOperation(subcircuit))
converted_circuit = circuit.copy()
cgoc.ConvertToSycamoreGates().optimize_circuit(converted_circuit)
# Verify that the CircuitOperation was preserved.
ops = list(converted_circuit.all_operations())
assert isinstance(ops[0], cirq.CircuitOperation)
# Verify that the contents of the CircuitOperation were optimized.
reconverted_subcircuit = ops[0].circuit.unfreeze().copy()
cgoc.ConvertToSycamoreGates().optimize_circuit(reconverted_subcircuit)
assert ops[0].circuit == reconverted_subcircuit
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(
circuit, converted_circuit, atol=1e-8
)


def test_unsupported_gate():
class UnknownGate(cirq.TwoQubitGate):
pass

q0, q1 = cirq.LineQubit.range(2)
circuit = cirq.Circuit(UnknownGate()(q0, q1))
with pytest.raises(ValueError, match='Unrecognized gate: '):
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)


def test_nested_unsupported_gate():
class UnknownGate(cirq.TwoQubitGate):
pass

q0 = cirq.LineQubit(0)
q1 = cirq.LineQubit(1)
subcircuit = cirq.FrozenCircuit(UnknownGate()(q0, q1))
circuit = cirq.Circuit(cirq.CircuitOperation(subcircuit))
circuit = cirq.Circuit(UnknownGate()(q0, q1))
with pytest.raises(ValueError, match='Unrecognized gate: '):
cgoc.ConvertToSycamoreGates().optimize_circuit(circuit)

Expand Down
33 changes: 0 additions & 33 deletions docs/google/best_practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,39 +49,6 @@ my_circuit = cirq.Circuit()
sycamore_circuit = cg.optimized_for_sycamore(my_circuit, new_device=cg.Sycamore, optimizer_type='sqrt_iswap')
```

### Using CircuitOperation to reduce circuit size

Particularly large batches (or sweeps) of circuits may encounter errors when
sent to Quantum Engine due to an upper limit on request size. If the circuits
in question have a repetitive structure, `cirq.CircuitOperation`s can be used
to reduce the request size and avoid this limit.

`optimized_for_sycamore` will preserve `CircuitOperation`s while optimizing
their contents.

```python
import cirq
import cirq_google as cg

# Repeatedly apply Hadamard and measurement to 10 qubits.
my_circuit = cirq.Circuit()
qubits = cirq.GridQubit.rect(2, 5)
for i in range(100):
my_circuit.append(cirq.H.on_each(*qubits))
for q in qubits:
my_circuit.append(cirq.measure(q, key=f'm{q}'))

# The same circuit, but defined using CircuitOperations.
# This is ~1000x smaller when serialized!
sub_circuit = cirq.Circuit(cirq.H(qubits[0]), cirq.measure(qubits[0], key='m'))
circuit_op = cirq.CircuitOperation(sub_circuit.freeze())
circuit_op = circuit_op.with_qubits([q])
circuit_op = circuit_op.with_measurement_key_mapping({'m': f'm{q}'})
circuit_op = circuit_op.repeat(100)
short_circuit = cirq.Circuit(circuit_op for q in qubits)
```


## Running circuits faster

The following sections give tips and tricks that allow you to improve your
Expand Down
9 changes: 0 additions & 9 deletions docs/google/devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,15 +223,6 @@ For decay experiments and other applications, a WaitGate is provided
that causes the device to idle for a specified amount of time.
This can be accomplished by specifying a `cirq.WaitGate`.


### Subcircuits

Circuits with a repetitive structure can benefit from using
`cirq.CircuitOperation` to specify "subcircuits" within the overall circuit.
Using this type condenses the serialized representation of the circuit, which
may help for circuits that would otherwise run into size limitations.


## Specific Device Layouts

The following devices are provided as part of cirq and can help you get your
Expand Down