-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add random circuit generator + tests
- Loading branch information
Showing
5 changed files
with
300 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Random Circuit\n", | ||
"Generates a random quantum circuit\n", | ||
"\n", | ||
"Random quantum circuits are important in quantum computing for several reasons:\n", | ||
"\n", | ||
"<u>Rapid Circuit Generation for Testing</u>\n", | ||
"\n", | ||
"Random quantum circuits are integral for quickly generating diverse and intricate test scenarios. This speed in creation allows for efficient and thorough testing of quantum computing systems, ensuring their readiness for complex tasks.\n", | ||
"\n", | ||
"<u> Enhancing Benchmarking and Hardware Evaluation</u>\n", | ||
"\n", | ||
"These circuits play a pivotal role in quantum benchmarking, providing a deeper and more accurate assessment of hardware quality and operational fidelity. This is crucial for ensuring that quantum systems meet the necessary standards for precision and reliability.\n", | ||
"\n", | ||
"<u> Comparing Quantum Architectures</u>\n", | ||
"\n", | ||
"These circuits enable objective and standardized comparisons across different quantum architectures. Such comparisons are fundamental to the advancement of quantum technology, ensuring that development is guided by accurate and impartial assessments.\n", | ||
"\n", | ||
"<u> Error Identification and System Optimization</u>\n", | ||
"\n", | ||
"By deploying random quantum circuits, it's possible to uncover error patterns and limitations within quantum hardware. This identification is key for continuous improvement and optimization of quantum computing systems.\n", | ||
"\n", | ||
"<u> Aiding Quantum Algorithm Development</u>\n", | ||
"\n", | ||
"Lastly, random quantum circuits are instrumental in the development and testing of quantum algorithms. They are particularly useful for algorithms that require diverse and complex configurations, making them an essential tool for advancing quantum computational research." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Run on a local simulator" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 4, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"--Circuit--\n", | ||
"T : | 0 | 1 | 2 | 3 |4| 5 | 6 | 7 |8| 9 | 10 | 11 | 12 |13| 14 | 15 | 16 |\n", | ||
" \n", | ||
"q0 : -C---C------------ZZ(0.19)---ZZ(4.77)---------------------------------ISWAP----------Y-Si-----------C-------------PHASE10(2.39)-H-----------------------------------------------------\n", | ||
" | | | | | | | \n", | ||
"q1 : -|-I-|-GPi2(3.18)-|--------X-|--------MS(6.01, 2.11, 0.58)------------|-----------------------------PHASE01(4.86)-C-------------PHASE01(3.36)-I--MS(4.30, 5.30, 4.88)-Rx(4.12)---SWAP-\n", | ||
" | | | | | | | | | | \n", | ||
"q2 : -V---|------------|--------|-ZZ(4.77)-|----------------------ECR-C----|-----YY(3.63)-V-ECR----------GPi2(4.41)------------------|----------------|-------------------------------|----\n", | ||
" | | | | | | | | | | | | \n", | ||
"q3 : -----|------------ZZ(0.19)-|-Y--------|--------------------H-ECR-SWAP-ISWAP-|--------V-|---Rx(1.68)-----------------------------|----------------|-------------------------------SWAP-\n", | ||
" | | | | | | | | \n", | ||
"q4 : -----Y---------------------C----------MS(6.01, 2.11, 0.58)-------SWAP-------YY(3.63)---ECR--------------------------------------C----------------MS(4.30, 5.30, 4.88)-GPi2(5.51)------\n", | ||
"\n", | ||
"T : | 0 | 1 | 2 | 3 |4| 5 | 6 | 7 |8| 9 | 10 | 11 | 12 |13| 14 | 15 | 16 |\n", | ||
"\n", | ||
"--Counts--\n", | ||
"Counter({'11100': 24, '11110': 11, '11010': 10, '01100': 9, '11000': 9, '01101': 8, '01110': 8, '11101': 7, '11001': 5, '11011': 4, '11111': 3, '01011': 2})\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"from braket.devices import LocalSimulator\n", | ||
"from braket.experimental.algorithms.random_circuit import random_circuit\n", | ||
"\n", | ||
"\n", | ||
"# Code here\n", | ||
"local_simulator = LocalSimulator()\n", | ||
"circuit = random_circuit(num_qubits=5, num_gates=30, max_operands=3, 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)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [] | ||
} | ||
], | ||
"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.6" | ||
}, | ||
"vscode": { | ||
"interpreter": { | ||
"hash": "5904cb9a2089448a2e1aeb5d493d227c9de33e591d7c07e4016fb81e71061a5d" | ||
} | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 4 | ||
} |
18 changes: 18 additions & 0 deletions
18
src/braket/experimental/algorithms/random_circuit/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# 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 braket.experimental.algorithms.random_circuit.random_circuit import ( # noqa: F401 | ||
filter_gate_set, | ||
random_circuit, | ||
run_random_circuit, | ||
) |
7 changes: 7 additions & 0 deletions
7
src/braket/experimental/algorithms/random_circuit/random_circuit.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. It's designed to construct a circuit with a specified number of qubits, instructions, and a maximum number of qubits the gate acts on. This function is useful for creating diverse quantum circuits for testing quantum algorithms or for benchmarking gate-based QPUs. | ||
|
||
<!-- | ||
[metadata-name]: Random Quantum Circuit Generator | ||
[metadata-tags]: Textbook | ||
[metadata-url]: https://github.com/aws-samples/amazon-braket-algorithm-library/tree/main/src/braket/experimental/algorithms/random_circuit | ||
--> |
99 changes: 99 additions & 0 deletions
99
src/braket/experimental/algorithms/random_circuit/random_circuit.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import inspect | ||
import math | ||
import random | ||
|
||
from braket.circuits import Circuit, Instruction, gates | ||
from braket.devices import Device | ||
from braket.tasks import QuantumTask | ||
|
||
|
||
def filter_gate_set(max_operands: int): | ||
""" | ||
Filters and returns Braket gate classes that require a maximum number of qubits. | ||
Args: | ||
max_operands (int): Maximum number of qubits (operands) the gate acts on. | ||
Returns: | ||
list: A list of gate classes constrained by the maximum number of operands. | ||
""" | ||
# Use list comprehension to select gate classes that meet the criteria | ||
# Check if it's a class and if it has the 'fixed_qubit_count' method | ||
# Check if qubit_count is an integer and if it's lower than or equal to min_qubits | ||
selected_classes = [ | ||
getattr(gates, cls_name) | ||
for cls_name in dir(gates) | ||
if isinstance((cls := getattr(gates, cls_name)), type) | ||
and hasattr(cls, "fixed_qubit_count") | ||
and isinstance((qubit_count := cls.fixed_qubit_count()), int) | ||
and qubit_count <= max_operands | ||
] | ||
return selected_classes | ||
|
||
|
||
def random_circuit(num_qubits: int, num_gates: int, max_operands: int, seed=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. | ||
max_operands (int): Maximum number of qubits for each gate. | ||
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) | ||
# Get filtered gate set based on the maximum number of operands (qubits) | ||
filtered_gate_set = filter_gate_set(max_operands) | ||
instructions = [] | ||
for _ in range(num_gates): | ||
# Choose a random gate from the filtered set | ||
gate_class = random.choice(filtered_gate_set) | ||
gate_qubits = gate_class.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_class.__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 | ||
gate = gate_class(*params) | ||
|
||
# Add the gate as an instruction | ||
instructions.append(Instruction(gate, qubits)) | ||
|
||
# Create a circuit with the list of instructions | ||
circuit = Circuit().add(instructions) | ||
return circuit | ||
|
||
|
||
def run_random_circuit( | ||
circuit: Circuit, | ||
device: Device, | ||
shots: int = 1000, | ||
) -> QuantumTask: | ||
"""Function to run random circuit and return measurement counts. | ||
Args: | ||
circuit (Circuit): Quantum Phase Estimation circuit | ||
device (Device): Braket device backend | ||
shots (int) : Number of measurement shots (default is 1000). | ||
Returns: | ||
QuantumTask: Task from running Quantum Phase Estimation | ||
""" | ||
|
||
task = device.run(circuit, shots=shots) | ||
|
||
return task |
57 changes: 57 additions & 0 deletions
57
test/unit_tests/braket/experimental/algorithms/random_circuit/test_random_circuit.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import pytest | ||
from braket.circuits import Circuit | ||
from braket.devices import LocalSimulator | ||
|
||
from braket.experimental.algorithms.random_circuit import ( | ||
filter_gate_set, | ||
random_circuit, | ||
run_random_circuit, | ||
) | ||
|
||
|
||
def test_filter_gate_set_returns_classes(): | ||
gate_classes = filter_gate_set(1) | ||
assert isinstance(gate_classes, list) | ||
assert all(isinstance(cls, type) for cls in gate_classes) | ||
|
||
|
||
def test_filter_gate_set_min_qubits(): | ||
min_qubits = 2 | ||
gate_classes = filter_gate_set(min_qubits) | ||
assert all(cls.fixed_qubit_count() >= min_qubits for cls in gate_classes) | ||
|
||
|
||
def test_random_circuit_returns_circuit(): | ||
circuit = random_circuit(3, 5, 1) | ||
assert isinstance(circuit, Circuit) | ||
|
||
|
||
def test_random_circuit_instruction_count(): | ||
num_gates = 5 | ||
circuit = random_circuit(3, num_gates, 1) | ||
assert len(circuit.instructions) == num_gates | ||
|
||
|
||
def test_random_circuit_consistency_with_seed(): | ||
circuit1 = random_circuit(3, 5, 1, seed=123) | ||
circuit2 = random_circuit(3, 5, 1, seed=123) | ||
assert circuit1 == circuit2 | ||
|
||
|
||
def test_random_circuit_variability_without_seed(): | ||
circuit1 = random_circuit(3, 5, 1) | ||
circuit2 = random_circuit(3, 5, 1) | ||
assert circuit1 != circuit2 | ||
|
||
|
||
def test_get_random_circuit_results(): | ||
local_simulator = LocalSimulator() | ||
circuit = random_circuit(2, 3, 1, seed=123) | ||
circuit.probability() | ||
|
||
result = run_random_circuit(circuit, local_simulator, shots=0).result() | ||
measured_probabilities = result.values[0].tolist() | ||
expected_probabilities = [0.5, 0.5, 0, 0] | ||
assert measured_probabilities == pytest.approx( | ||
expected_probabilities, rel=1e-5 | ||
), "The measured probabilities are not within the expected tolerance." |