Skip to content

Commit

Permalink
Add random circuit algo (#139)
Browse files Browse the repository at this point in the history
Co-authored-by: Ryan Shaffer <[email protected]>
  • Loading branch information
ykharkov and rmshaffer authored Mar 29, 2024
1 parent d240d09 commit 62643bd
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 0 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ Running notebooks locally requires additional dependencies located in [notebooks
| Quantum PCA | [Quantum_Principal_Component_Analysis.ipynb](notebooks/advanced_algorithms/Quantum_Principal_Component_Analysis.ipynb) | [He2022](https://ieeexplore.ieee.org/document/9669030) |
| QMC | [Quantum_Computing_Quantum_Monte_Carlo.ipynb](notebooks/advanced_algorithms/Quantum_Computing_Quantum_Monte_Carlo.ipynb) | [Motta2018](https://wires.onlinelibrary.wiley.com/doi/10.1002/wcms.1364), [Peruzzo2014](https://www.nature.com/articles/ncomms5213) |


| Auxiliary functions | Notebook |
| ----- | ----- |
| Random circuit generator | [Random_Circuit.ipynb](notebooks/auxiliary_functions/Random_Circuit.ipynb) |

---
### Community repos

Expand Down
109 changes: 109 additions & 0 deletions notebooks/auxiliary_functions/Random_Circuit.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Random Circuit\n",
"\n",
"Generates random quantum circuits using the Amazon Braket SDK.\n",
"\n",
"### Circuit Generation for Testing\n",
"\n",
"Random quantum circuits allow creation of a diverse set of circuits with a variety of output probability distributions. Users can utilize random circuits to test performance of quantum simulators and QPUs. \n",
"\n",
"### Benchmarking quantum compilation stacks\n",
"\n",
"Random circuits sampled from a fixed gate set (as in the example below) are often used for benchmarking performance of quantum compilation passes, such as circuit mapping, routing, or circuit optimization passes. "
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Run on a local simulator"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--Circuit--\n",
"T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │\n",
" ┌───┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ \n",
"q0 : ───●────────────────┤ X ├──────────────┤ XY(0.19) ├───────┤ Rz(4.77) ├───────┤ Rz(0.58) ├─┤ XY(4.59) ├─┤ XY(0.50) ├───●────┤ Rz(5.37) ├───┤ Rz(1.44) ├───────┤ Rz(1.33) ├────────────────────────────────────\n",
" │ └─┬─┘ └────┬─────┘ └──────────┘ └──────────┘ └────┬─────┘ └────┬─────┘ │ └──────────┘ └──────────┘ └──────────┘ \n",
" │ ┌──────────┐ │ ┌──────────┐ │ ┌───┐ ┌──────────┐ ┌──────────┐ │ │ ┌─┴─┐ ┌─────────────┐ ┌───┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ \n",
"q1 : ───┼───┤ Rx(0.88) ├───┼───┤ Rx(3.18) ├──────┼───────┤ X ├─┤ XY(2.82) ├───────┤ Rx(6.01) ├──────┼────────────┼───────┤ X ├─┤ PHASE(2.33) ├──────────────┤ X ├─┤ XY(2.90) ├───────┤ XY(4.12) ├─┤ PHASE(1.66) ├─\n",
" │ └──────────┘ │ └──────────┘ │ └─┬─┘ └────┬─────┘ └──────────┘ │ │ └───┘ └──────┬──────┘ └─┬─┘ └────┬─────┘ └────┬─────┘ └──────┬──────┘ \n",
" ┌─┴─┐ │ │ │ │ ┌────┴─────┐ │ ┌───┐ │ ┌──────────┐ │ │ ┌────┴─────┐ │ \n",
"q2 : ─┤ X ├────────────────┼─────────────────────┼─────────┼────────┼─────────●────────────────┤ XY(4.59) ├──────┼───────┤ X ├────────●────────┤ Rx(4.41) ├───┼────────┼─────────●───┤ XY(4.12) ├────────┼────────\n",
" └───┘ │ │ │ │ │ └──────────┘ │ └─┬─┘ └──────────┘ │ │ │ └──────────┘ │ \n",
" │ ┌────┴─────┐ │ ┌────┴─────┐ │ ┌──────────┐ ┌────┴─────┐ │ │ │ ┌─┴─┐ │ \n",
"q3 : ──────────────────────┼────────────────┤ XY(0.19) ├───┼───┤ XY(2.82) ├───┼───┤ Rx(2.14) ├──────────────┤ XY(0.50) ├───●──────────────────────────────────┼────────┼───────┤ X ├─────────────────────●────────\n",
" │ └──────────┘ │ └──────────┘ │ └──────────┘ └──────────┘ │ │ └───┘ \n",
" │ │ ┌─┴─┐ ┌──────────┐ ┌──────────┐ │ ┌────┴─────┐ ┌──────────┐ ┌──────────┐ \n",
"q4 : ──────────────────────●───────────────────────────────●────────────────┤ X ├─┤ Rz(5.56) ├─┤ Rz(1.21) ├───────────────────────────────────────────────────●───┤ XY(2.90) ├───────┤ Rz(1.38) ├──┤ Rx(3.39) ├───\n",
" └───┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ \n",
"T : │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │ 12 │\n",
"\n",
"--Counts--\n",
"Counter({'01011': 34, '00011': 21, '00001': 13, '00111': 10, '01001': 10, '01010': 3, '00000': 2, '00101': 2, '01000': 2, '10000': 1, '00010': 1, '11010': 1})\n"
]
}
],
"source": [
"from braket.circuits.gates import CNot, Rx, Rz, CPhaseShift, XY\n",
"from braket.devices import LocalSimulator\n",
"from braket.experimental.auxiliary_functions import random_circuit\n",
"\n",
"# Code here\n",
"local_simulator = LocalSimulator()\n",
"gate_set = [CNot, Rx, Rz, CPhaseShift, XY]\n",
"circuit = random_circuit(num_qubits=5, \n",
" num_gates=30,\n",
" gate_set=gate_set,\n",
" seed=42)\n",
"task = local_simulator.run(circuit, shots=100)\n",
"result = task.result()\n",
"print(\"--Circuit--\")\n",
"print(circuit)\n",
"print(\"\\n--Counts--\")\n",
"print(result.measurement_counts)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
},
"vscode": {
"interpreter": {
"hash": "5904cb9a2089448a2e1aeb5d493d227c9de33e591d7c07e4016fb81e71061a5d"
}
}
},
"nbformat": 4,
"nbformat_minor": 4
}
14 changes: 14 additions & 0 deletions src/braket/experimental/auxiliary_functions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, 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.

from .random_circuit import random_circuit # noqa: F401
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, 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.

from .random_circuit import random_circuit # noqa: F401
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
The `random_circuit` function generates a random quantum circuit using the Amazon Braket SDK.
The function creates a diverse set of circuits that can be used for testing Braket SDK functionality and compiler benchmarking.
<!--
[metadata-name]: Random Quantum Circuit Generator
[metadata-tags]: Auxiliary functions
[metadata-url]: https://github.com/amazon-braket/amazon-braket-algorithm-library/tree/main/src/braket/experimental/auxiliary_functions/random_circuit
-->
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import inspect
import math
import random
from typing import List, Optional

from braket.circuits import Circuit, Gate, Instruction
from braket.circuits.gates import CNot, H, S, T


def random_circuit(
num_qubits: int,
num_gates: int,
gate_set: Optional[List[Gate]] = None,
seed: Optional[int] = None,
) -> Circuit:
"""
Generates a random quantum circuit.
Args:
num_qubits (int): Number of qubits in the circuit.
num_gates (int): Number of instructions (gates) in the circuit.
gate_set (Optional[List[Gate]]): List of basis gates for the random circuit
(default is None).
seed (Optional[int]): Random seed for reproducibility (default is None).
Returns:
Circuit: random quantum circuit.
"""
# Set the seed if provided
if seed is not None:
random.seed(seed)

# Default gate_set (Clifford + T) if gate_set is None
if not gate_set:
gate_set = [CNot, S, T, H]

instructions = []
for _ in range(num_gates):
gate = random.choice(gate_set)
gate_qubits = gate.fixed_qubit_count()

# Select random qubits for the gate
qubits = random.sample(range(num_qubits), gate_qubits)

# Get the constructor's signature to determine required parameters
init_signature = inspect.signature(gate.__init__)

# Calculate the number of parameters (excluding 'self')
num_params = len(init_signature.parameters) - 1

# Generate random parameters for the gate in the range [0, 2*pi]
params = [random.uniform(0, 2 * math.pi) for _ in range(num_params)]

# Create the gate instance
g = gate(*params)

# Add the gate as an instruction
instructions.append(Instruction(g, qubits))

# Create a circuit with the list of instructions
circuit = Circuit().add(instructions)
return circuit
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from braket.circuits import Circuit
from braket.circuits.gates import XY, CNot, CPhaseShift, H, Rx, Ry, Rz, S, T

from braket.experimental.auxiliary_functions import random_circuit


def test_random_circuit_returns_circuit():
circuit = random_circuit(num_qubits=3, num_gates=5, seed=1)
assert isinstance(circuit, Circuit)


def test_random_circuit_instruction_count():
num_gates = 5
circuit = random_circuit(num_qubits=3, num_gates=num_gates, seed=1)
assert len(circuit.instructions) == num_gates


def test_random_circuit_consistency_with_seed():
circuit1 = random_circuit(num_qubits=3, num_gates=5, seed=1)
circuit2 = random_circuit(num_qubits=3, num_gates=5, seed=1)
assert circuit1 == circuit2


def test_random_circuit_variability_without_seed():
circuit1 = random_circuit(num_qubits=3, num_gates=5)
circuit2 = random_circuit(num_qubits=3, num_gates=5)
assert circuit1 != circuit2


def test_custom_gate_set():
gate_set = [CNot, H, S, T, Rx, Ry, Rz, XY, CPhaseShift]
circuit = random_circuit(num_qubits=3, num_gates=5, gate_set=gate_set, seed=1)

gate_from_gate_set = []
for instr in circuit.instructions:
gate_class = instr.operator.__class__
gate_from_gate_set.append(gate_class in gate_set)

assert all(gate_from_gate_set)

0 comments on commit 62643bd

Please sign in to comment.