Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 189 additions & 20 deletions docs/circuits.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
},
"outputs": [],
"source": [
"qubits = [cirq.GridQubit(x, y) for x in range(3) for y in range(3)]\n",
"qubits = cirq.GridQubit.square(3)\n",
"\n",
"print(qubits[0])"
]
Expand Down Expand Up @@ -224,10 +224,9 @@
},
"outputs": [],
"source": [
"from cirq.ops import CZ, H\n",
"q0, q1, q2 = [cirq.GridQubit(i, 0) for i in range(3)]\n",
"circuit = cirq.Circuit()\n",
"circuit.append([CZ(q0, q1), H(q2)])\n",
"circuit.append([cirq.CZ(q0, q1), cirq.H(q2)])\n",
"\n",
"print(circuit)"
]
Expand All @@ -249,7 +248,7 @@
},
"outputs": [],
"source": [
"circuit.append([H(q0), CZ(q1, q2)])\n",
"circuit.append([cirq.H(q0), cirq.CZ(q1, q2)])\n",
"\n",
"print(circuit)"
]
Expand All @@ -272,7 +271,7 @@
"outputs": [],
"source": [
"circuit = cirq.Circuit()\n",
"circuit.append([CZ(q0, q1), H(q2), H(q0), CZ(q1, q2)])\n",
"circuit.append([cirq.CZ(q0, q1), cirq.H(q2), cirq.H(q0), cirq.CZ(q1, q2)])\n",
"\n",
"print(circuit)"
]
Expand Down Expand Up @@ -316,8 +315,8 @@
"from cirq.circuits import InsertStrategy\n",
"\n",
"circuit = cirq.Circuit()\n",
"circuit.append([CZ(q0, q1)])\n",
"circuit.append([H(q0), H(q2)], strategy=InsertStrategy.EARLIEST)\n",
"circuit.append([cirq.CZ(q0, q1)])\n",
"circuit.append([cirq.H(q0), cirq.H(q2)], strategy=InsertStrategy.EARLIEST)\n",
"\n",
"print(circuit)"
]
Expand All @@ -344,7 +343,9 @@
"outputs": [],
"source": [
"circuit = cirq.Circuit()\n",
"circuit.append([H(q0), H(q1), H(q2)], strategy=InsertStrategy.NEW)\n",
"circuit.append(\n",
" [cirq.H(q0), cirq.H(q1), cirq.H(q2)], strategy=InsertStrategy.NEW\n",
")\n",
"\n",
"print(circuit)"
]
Expand Down Expand Up @@ -385,9 +386,11 @@
"outputs": [],
"source": [
"circuit = cirq.Circuit()\n",
"circuit.append([CZ(q1, q2)])\n",
"circuit.append([CZ(q1, q2)])\n",
"circuit.append([H(q0), H(q1), H(q2)], strategy=InsertStrategy.INLINE)\n",
"circuit.append([cirq.CZ(q1, q2)])\n",
"circuit.append([cirq.CZ(q1, q2)])\n",
"circuit.append(\n",
" [cirq.H(q0), cirq.H(q1), cirq.H(q2)], strategy=InsertStrategy.INLINE\n",
")\n",
"\n",
"print(circuit)"
]
Expand Down Expand Up @@ -422,8 +425,10 @@
"outputs": [],
"source": [
"circuit = cirq.Circuit()\n",
"circuit.append([H(q0)])\n",
"circuit.append([CZ(q1,q2), H(q0)], strategy=InsertStrategy.NEW_THEN_INLINE)\n",
"circuit.append([cirq.H(q0)])\n",
"circuit.append(\n",
" [cirq.CZ(q1,q2), cirq.H(q0)], strategy=InsertStrategy.NEW_THEN_INLINE\n",
")\n",
"\n",
"print(circuit)"
]
Expand Down Expand Up @@ -468,10 +473,10 @@
"outputs": [],
"source": [
"def my_layer():\n",
" yield CZ(q0, q1)\n",
" yield [H(q) for q in (q0, q1, q2)]\n",
" yield [CZ(q1, q2)]\n",
" yield [H(q0), [CZ(q1, q2)]]\n",
" yield cirq.CZ(q0, q1)\n",
" yield [cirq.H(q) for q in (q0, q1, q2)]\n",
" yield [cirq.CZ(q1, q2)]\n",
" yield [cirq.H(q0), [cirq.CZ(q1, q2)]]\n",
"\n",
"circuit = cirq.Circuit()\n",
"circuit.append(my_layer())\n",
Expand Down Expand Up @@ -521,7 +526,7 @@
},
"outputs": [],
"source": [
"circuit = cirq.Circuit(H(q0), H(q1))\n",
"circuit = cirq.Circuit(cirq.H(q0), cirq.H(q1))\n",
"print(circuit)"
]
},
Expand All @@ -544,7 +549,7 @@
},
"outputs": [],
"source": [
"circuit = cirq.Circuit(H(q0), CZ(q0, q1))\n",
"circuit = cirq.Circuit(cirq.H(q0), cirq.CZ(q0, q1))\n",
"for moment in circuit:\n",
" print(moment)"
]
Expand All @@ -566,7 +571,7 @@
},
"outputs": [],
"source": [
"circuit = cirq.Circuit(H(q0), CZ(q0, q1), H(q1), CZ(q0, q1))\n",
"circuit = cirq.Circuit(cirq.H(q0), cirq.CZ(q0, q1), cirq.H(q1), cirq.CZ(q0, q1))\n",
"print(circuit[1:3])"
]
},
Expand All @@ -579,6 +584,170 @@
"Especially useful is dropping the last moment (which are often just measurements): `circuit[:-1]`, or reversing a circuit: `circuit[::-1]`.\n"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does CircuitOperation add a link to the reference page or we need to write cirq.CircuitOperation ? Please change, here and elsewhere, if it's the latter.


Reply via ReviewNB

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done for the first appearance of CircuitOperation - I think this is our strategy in general, similar to Wikipedia-style linking.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should also add a section to explain circuit_op.repeat_until and circuit_op.mapped_circuit.


Reply via ReviewNB

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

repeat_until requires measurement and classical control, neither of which are discussed in this high-level doc. Happy to add mapped_circuit, though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

qubits = [cirq.GridQubit(x, y) for x in range(3) for y in range(3)] can be qubits=cirq.GridQubit.square(3)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

]
},
{
"cell_type": "markdown",
"metadata": {
"id": "e31b4ff57134"
},
"source": [
"### Nesting circuits with CircuitOperation\n",
"\n",
"Circuits can be nested inside one another with `cirq.CircuitOperation`. This is useful for concisely defining large, repetitive circuits, as the repeated section can be defined once and then be reused elsewhere. Circuits that need to be serialized especially benefit from this, as loops and functions used in the Python construction of a circuit are otherwise not captured in serialization.\n",
"\n",
"The subcircuit must first be \"frozen\" to indicate that no further changes will be made to it."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "b3772732f57b"
},
"outputs": [],
"source": [
"subcircuit = cirq.Circuit(\n",
" cirq.H(q1), cirq.CZ(q0, q1), cirq.CZ(q2, q1), cirq.H(q1)\n",
")\n",
"subcircuit_op = cirq.CircuitOperation(subcircuit.freeze())\n",
"circuit = cirq.Circuit(cirq.H(q0), cirq.H(q2), subcircuit_op)\n",
"print(circuit)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3557398496c2"
},
"source": [
"Frozen circuits can also be constructed directly, for convenience."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "3d80776e09fe"
},
"outputs": [],
"source": [
"circuit = cirq.Circuit(\n",
" cirq.CircuitOperation(\n",
" cirq.FrozenCircuit(\n",
" cirq.H(q1), cirq.CZ(q0, q1), cirq.CZ(q2, q1), cirq.H(q1)\n",
" )\n",
" )\n",
")\n",
"print(circuit)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "e2c83225f05a"
},
"source": [
"A `CircuitOperation` is sort of like a function: by default, it will behave like the circuit it contains, but we can also pass arguments to it that alter the qubits it operates on, the number of times it repeats, and other properties. `CircuitOperation`s can also be referenced multiple times within the same \"outer\" circuit for conciseness."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "62d50a44bdb3"
},
"outputs": [],
"source": [
"subcircuit_op = cirq.CircuitOperation(cirq.FrozenCircuit(cirq.CZ(q0, q1)))\n",
"\n",
"# Create a copy of subcircuit_op that repeats twice...\n",
"repeated_subcircuit_op = subcircuit_op.repeat(2)\n",
"\n",
"# ...and another copy that replaces q0 with q2 to perform CZ(q2, q1).\n",
"moved_subcircuit_op = subcircuit_op.with_qubit_mapping({q0: q2})\n",
"circuit = cirq.Circuit(\n",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful to have some line comments to further explain this example.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

" repeated_subcircuit_op,\n",
" moved_subcircuit_op,\n",
")\n",
"print(circuit)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "4e9d0e01508a"
},
"source": [
"For the most part, a `CircuitOperation` behaves just like a regular `Operation`: its qubits are the qubits of the contained circuit (after applying any provided mapping), and it can be placed inside any `Moment` that doesn't already contain operations on those qubits. This means that `CircuitOperation`s can be used to represent more complex operation timing, such as three operations on one qubit in parallel with two operations on another:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "1b06bfaddfdf"
},
"outputs": [],
"source": [
"subcircuit_op = cirq.CircuitOperation(cirq.FrozenCircuit(cirq.H(q0)))\n",
"circuit = cirq.Circuit(\n",
" subcircuit_op.repeat(3),\n",
" subcircuit_op.repeat(2).with_qubit_mapping({q0: q1})\n",
")\n",
"print(circuit)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "c8a67e3ec86d"
},
"source": [
"`CircuitOperation`s can also be nested within each other to arbitrary depth."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "4acf1a942b75"
},
"outputs": [],
"source": [
"qft_1 = cirq.CircuitOperation(cirq.FrozenCircuit(cirq.H(q0)))\n",
"qft_2 = cirq.CircuitOperation(\n",
" cirq.FrozenCircuit(cirq.H(q1), cirq.CZ(q0, q1) ** 0.5, qft_1)\n",
")\n",
"qft_3 = cirq.CircuitOperation(\n",
" cirq.FrozenCircuit(\n",
" cirq.H(q2), cirq.CZ(q1, q2) ** 0.5, cirq.CZ(q0, q2) ** 0.25, qft_2\n",
" )\n",
")\n",
"# etc."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "98a7293a6e4b"
},
"source": [
"Finally, the `mapped_circuit` method will return the circuit that a `CircuitOperation` represents after all repetitions and remappings have been applied. By default, this only \"unrolls\" a single layer of `CircuitOperation`s; to recursively unroll all layers, we can pass `deep=True` to this method."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "7a0b7fc127f2"
},
"outputs": [],
"source": [
"print('Single layer unroll:')\n",
"print(qft_3.mapped_circuit(deep=False))\n",
"print('Recursive unroll:')\n",
"print(qft_3.mapped_circuit(deep=True))"
]
},
{
"cell_type": "markdown",
"metadata": {
Expand Down