-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Add CircuitOperation blurb #5399
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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])" | ||
| ] | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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", | ||
|
|
@@ -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)" | ||
| ] | ||
| }, | ||
|
|
@@ -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)" | ||
| ] | ||
|
|
@@ -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])" | ||
| ] | ||
| }, | ||
|
|
@@ -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" | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does Reply via ReviewNB
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done for the first appearance of
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Reply via ReviewNB
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done.
augustehirth marked this conversation as resolved.
Show resolved
Hide resolved
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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", | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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": { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.