This is an automated email from the ASF dual-hosted git repository.
rawkintrevo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/mahout.git
The following commit(s) were added to refs/heads/main by this push:
new de2d5a7e1 Add new linting workflow using Ruff (#568)
de2d5a7e1 is described below
commit de2d5a7e101afbb9e721aad964ca202110a1c51d
Author: Guan Ming(Wesley) Chiu <[email protected]>
AuthorDate: Tue Oct 7 04:32:55 2025 +0800
Add new linting workflow using Ruff (#568)
---
.github/scripts/checks/general_review.py | 61 +++++++++++++++++---------------
.github/scripts/pr_review_checks.py | 1 -
.github/scripts/review_pr.py | 17 ++++++---
.github/workflows/lint.yml | 50 ++++++++++++++++++++++++++
examples/Optimization_Example.ipynb | 20 ++++++-----
examples/Simple_Example.ipynb | 20 +++++------
examples/quantum_teleportation.py | 10 +++---
examples/simple_example.py | 10 +++---
pyproject.toml | 2 +-
qumat/__init__.py | 2 ++
qumat/amazon_braket_backend.py | 37 ++++++++++++++-----
qumat/cirq_backend.py | 46 ++++++++++++++++++------
qumat/qiskit_backend.py | 47 +++++++++++++++++-------
qumat/qumat.py | 29 ++++++++++-----
testing/qiskit_helpers.py | 18 +++++-----
testing/qumat_helpers.py | 22 +++++++-----
testing/test_final_quantum_states.py | 14 +++++---
17 files changed, 281 insertions(+), 125 deletions(-)
diff --git a/.github/scripts/checks/general_review.py
b/.github/scripts/checks/general_review.py
index 9215e5a1f..c93b1a91c 100644
--- a/.github/scripts/checks/general_review.py
+++ b/.github/scripts/checks/general_review.py
@@ -15,7 +15,7 @@
# limitations under the License.
#
import ast
-from github import Github
+
class GeneralReviewCheck:
def __init__(self, client, model_name):
@@ -26,26 +26,28 @@ class GeneralReviewCheck:
comments = []
analyzed = False
- if file.filename.endswith('.py'):
+ if file.filename.endswith(".py"):
analyzed = True
- content = repo.get_contents(file.filename,
ref=pr.head.sha).decoded_content.decode()
+ content = repo.get_contents(
+ file.filename, ref=pr.head.sha
+ ).decoded_content.decode()
# Basic code analysis
try:
tree = ast.parse(content)
analysis = self.analyze_code_structure(tree)
if analysis:
- comments.append({
- "path": file.filename,
- "body": analysis,
- "line": 1
- })
+ comments.append(
+ {"path": file.filename, "body": analysis, "line": 1}
+ )
except SyntaxError as e:
- comments.append({
- "path": file.filename,
- "body": f"⚠️ Syntax error found:\n{e}",
- "line": 1
- })
+ comments.append(
+ {
+ "path": file.filename,
+ "body": f"⚠️ Syntax error found:\n{e}",
+ "line": 1,
+ }
+ )
return comments, analyzed
@@ -57,19 +59,26 @@ class GeneralReviewCheck:
if isinstance(node, ast.ClassDef):
methods = [n for n in node.body if isinstance(n,
ast.FunctionDef)]
if len(methods) > 10:
- analysis.append(f"- Class '{node.name}' has {len(methods)}
methods. Consider splitting into smaller classes.")
+ analysis.append(
+ f"- Class '{node.name}' has {len(methods)} methods.
Consider splitting into smaller classes."
+ )
# Check for long functions
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef):
lines = node.end_lineno - node.lineno if node.end_lineno else 0
if lines > 50:
- analysis.append(f"- Function '{node.name}' is {lines}
lines long. Consider breaking it into smaller functions.")
+ analysis.append(
+ f"- Function '{node.name}' is {lines} lines long.
Consider breaking it into smaller functions."
+ )
# Check for TODO comments
for node in ast.walk(tree):
if isinstance(node, ast.Expr) and isinstance(node.value,
ast.Constant):
- if isinstance(node.value.value, str) and 'TODO' in
node.value.value.upper():
+ if (
+ isinstance(node.value.value, str)
+ and "TODO" in node.value.value.upper()
+ ):
analysis.append(f"- TODO comment found:
{node.value.value}")
if analysis:
@@ -99,21 +108,17 @@ Provide your analysis in markdown format with these
sections:
response = self.client.chat.completions.create(
model=self.model_name,
- messages=[{
- "role": "system",
- "content": "You are an experienced code reviewer. Provide a
high-level analysis of pull requests."
- }, {
- "role": "user",
- "content": prompt
- }]
+ messages=[
+ {
+ "role": "system",
+ "content": "You are an experienced code reviewer. Provide
a high-level analysis of pull requests.",
+ },
+ {"role": "user", "content": prompt},
+ ],
)
return response.choices[0].message.content
def process_pr(self, pr):
general_analysis = self.generate_general_impression(pr)
- return [{
- "path": "GENERAL",
- "body": general_analysis,
- "line": 0
- }], True
+ return [{"path": "GENERAL", "body": general_analysis, "line": 0}], True
diff --git a/.github/scripts/pr_review_checks.py
b/.github/scripts/pr_review_checks.py
deleted file mode 100644
index 007d83091..000000000
--- a/.github/scripts/pr_review_checks.py
+++ /dev/null
@@ -1 +0,0 @@
-from checks.general_review import GeneralReviewCheck
diff --git a/.github/scripts/review_pr.py b/.github/scripts/review_pr.py
index 5b283433b..a74e86086 100644
--- a/.github/scripts/review_pr.py
+++ b/.github/scripts/review_pr.py
@@ -20,27 +20,36 @@ import sys
from github import Github
from gofannon.github.pr_review_tool import PRReviewTool
+
def check_env_vars():
required_vars = [
- 'GITHUB_TOKEN', 'OPENAI_API_KEY', 'OPENAI_BASE_URL',
'OPENAI_MODEL_NAME', 'PR_NUMBER', 'REPO_NAME'
+ "GITHUB_TOKEN",
+ "OPENAI_API_KEY",
+ "OPENAI_BASE_URL",
+ "OPENAI_MODEL_NAME",
+ "PR_NUMBER",
+ "REPO_NAME",
]
for var in required_vars:
if not os.environ.get(var):
sys.exit(f"Error: Required environment variable '{var}' is
missing.")
+
check_env_vars()
+
def main():
- pr_number = int(os.environ['PR_NUMBER'])
- repo_name = os.environ['REPO_NAME']
+ pr_number = int(os.environ["PR_NUMBER"])
+ repo_name = os.environ["REPO_NAME"]
pr_review_tool = PRReviewTool()
review_summary = pr_review_tool.fn(pr_number=pr_number,
repo_name=repo_name)
# Post the review comment to the pull request using PyGithub.
- g = Github(os.environ['GITHUB_TOKEN'])
+ g = Github(os.environ["GITHUB_TOKEN"])
repo = g.get_repo(repo_name)
pr = repo.get_pull(pr_number)
pr.create_issue_comment(review_summary)
+
if __name__ == "__main__":
main()
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 000000000..7e370e20d
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,50 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License 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.
+
+name: Lint
+
+on:
+ pull_request:
+ paths:
+ - "**/*.py"
+ push:
+ branches:
+ - main
+ paths:
+ - "**/*.py"
+
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v5
+
+ - name: Set up Python
+ uses: actions/setup-python@v6
+ with:
+ python-version: "3.10"
+
+ - name: Install Poetry
+ run: pip install poetry
+
+ - name: Install dependencies
+ run: poetry install --with dev
+
+ - name: Run Ruff Linter
+ run: poetry run ruff check .
+
+ - name: Run Ruff Formatter
+ run: poetry run ruff format --check .
diff --git a/examples/Optimization_Example.ipynb
b/examples/Optimization_Example.ipynb
index d5ce65bea..320b02236 100644
--- a/examples/Optimization_Example.ipynb
+++ b/examples/Optimization_Example.ipynb
@@ -56,8 +56,8 @@
"\n",
"# Configure the backend to use Qiskit with a simulator\n",
"backend_config = {\n",
- " 'backend_name': 'qiskit',\n",
- " 'backend_options': {'simulator_type': 'qasm_simulator', 'shots':
1024}\n",
+ " \"backend_name\": \"qiskit\",\n",
+ " \"backend_options\": {\"simulator_type\": \"qasm_simulator\",
\"shots\": 1024},\n",
"}\n",
"\n",
"# Create an instance of QuMat\n",
@@ -83,9 +83,9 @@
"qumat_instance.create_empty_circuit(1)\n",
"\n",
"# Apply parameterized RX, RY, and RZ gates\n",
- "qumat_instance.apply_rx_gate(0, 'theta')\n",
- "qumat_instance.apply_ry_gate(0, 'phi')\n",
- "qumat_instance.apply_rz_gate(0, 'lambda')"
+ "qumat_instance.apply_rx_gate(0, \"theta\")\n",
+ "qumat_instance.apply_ry_gate(0, \"phi\")\n",
+ "qumat_instance.apply_rz_gate(0, \"lambda\")"
]
},
{
@@ -106,22 +106,24 @@
"# Example optimization loop\n",
"\n",
"# Initial parameter values\n",
- "current_parameters = {'theta': 0, 'phi': 0, 'lambda': 0}\n",
+ "current_parameters = {\"theta\": 0, \"phi\": 0, \"lambda\": 0}\n",
+ "\n",
"\n",
"# Define a simple placeholder cost function\n",
"def your_cost_function():\n",
" # Placeholder: replace with a real function in actual applications\n",
" return 0\n",
"\n",
+ "\n",
"# Run the optimization loop\n",
"for iteration in range(10): # Reduced iteration count for brevity\n",
" cost = your_cost_function() # Evaluate the cost function\n",
"\n",
" # Update parameter(s) based on some optimization logic\n",
" # This is a placeholder update mechanism\n",
- " current_parameters['theta'] += 0.1\n",
- " current_parameters['phi'] += 0.1\n",
- " current_parameters['lambda'] += 0.1\n",
+ " current_parameters[\"theta\"] += 0.1\n",
+ " current_parameters[\"phi\"] += 0.1\n",
+ " current_parameters[\"lambda\"] += 0.1\n",
"\n",
" # Execute the circuit with the updated parameters\n",
" result =
qumat_instance.execute_circuit(parameter_values=current_parameters)\n",
diff --git a/examples/Simple_Example.ipynb b/examples/Simple_Example.ipynb
index 5af5337d2..1a01d87c8 100644
--- a/examples/Simple_Example.ipynb
+++ b/examples/Simple_Example.ipynb
@@ -47,11 +47,8 @@
"source": [
"# Create an instance of QuMat with a qiskit backend configuration\n",
"qiskit_backend_config = {\n",
- " 'backend_name': 'qiskit',\n",
- " 'backend_options': {\n",
- " 'simulator_type': 'aer_simulator',\n",
- " 'shots': 1024\n",
- " }\n",
+ " \"backend_name\": \"qiskit\",\n",
+ " \"backend_options\": {\"simulator_type\": \"aer_simulator\",
\"shots\": 1024},\n",
"}\n",
"qiskit_circuit = QuMat(qiskit_backend_config)\n",
"\n",
@@ -75,12 +72,11 @@
"source": [
"# Create an instance of QuMat with a cirq backend configuration\n",
"cirq_backend_config = {\n",
- " 'backend_name': 'cirq', # Replace with the actual backend you want
to use\n",
- " 'backend_options': {\n",
- " 'simulator_type': 'default',\n",
- " 'shots': 1024 # Number of shots for measurement\n",
- "\n",
- " }\n",
+ " \"backend_name\": \"cirq\", # Replace with the actual backend you
want to use\n",
+ " \"backend_options\": {\n",
+ " \"simulator_type\": \"default\",\n",
+ " \"shots\": 1024, # Number of shots for measurement\n",
+ " },\n",
"}\n",
"cirq_circuit = QuMat(cirq_backend_config)\n",
"\n",
@@ -91,7 +87,7 @@
"cirq_circuit.apply_hadamard_gate(qubit_index=0)\n",
"cirq_circuit.apply_cnot_gate(control_qubit_index=0,
target_qubit_index=1)\n",
"cirq_circuit.apply_pauli_x_gate(qubit_index=0)\n",
- "cirq_circuit.execute_circuit()\n"
+ "cirq_circuit.execute_circuit()"
]
}
],
diff --git a/examples/quantum_teleportation.py
b/examples/quantum_teleportation.py
index 3f69f2558..9eaf1d08a 100644
--- a/examples/quantum_teleportation.py
+++ b/examples/quantum_teleportation.py
@@ -2,11 +2,11 @@
# Initialize your QuMat quantum computer with the chosen backend
backend_config = {
- 'backend_name': 'qiskit_simulator',
- 'backend_options': {
- 'simulator_type': 'qasm_simulator',
- 'shots': 1 # Set to 1 for teleportation
- }
+ "backend_name": "qiskit_simulator",
+ "backend_options": {
+ "simulator_type": "qasm_simulator",
+ "shots": 1, # Set to 1 for teleportation
+ },
}
quantum_computer = QuMat(backend_config)
diff --git a/examples/simple_example.py b/examples/simple_example.py
index bba7b166d..8079d6312 100644
--- a/examples/simple_example.py
+++ b/examples/simple_example.py
@@ -3,11 +3,11 @@ from qumat import QuMat
# Create an instance of QuantumComputer with a specific backend configuration
backend_config = {
- 'backend_name': 'qiskit', # Replace with the actual backend you want to
use
- 'backend_options': {
- 'simulator_type': 'aer_simulator',
- 'shots': 1024 # Number of shots for measurement
- }
+ "backend_name": "qiskit", # Replace with the actual backend you want to
use
+ "backend_options": {
+ "simulator_type": "aer_simulator",
+ "shots": 1024, # Number of shots for measurement
+ },
}
qumat = QuMat(backend_config)
diff --git a/pyproject.toml b/pyproject.toml
index 22e670d91..68431d907 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -15,7 +15,7 @@ dependencies = [
]
[project.optional-dependencies]
-dev = ["pytest>=8.1.1"]
+dev = ["pytest>=8.1.1", "ruff>=0.13.1"]
[build-system]
requires = ["poetry-core"]
diff --git a/qumat/__init__.py b/qumat/__init__.py
index 261e9180d..039ff44ab 100644
--- a/qumat/__init__.py
+++ b/qumat/__init__.py
@@ -1 +1,3 @@
from .qumat import QuMat
+
+__all__ = ["QuMat"]
diff --git a/qumat/amazon_braket_backend.py b/qumat/amazon_braket_backend.py
index efa533b69..3378a46ce 100644
--- a/qumat/amazon_braket_backend.py
+++ b/qumat/amazon_braket_backend.py
@@ -14,54 +14,73 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-from braket.aws import AwsQuantumSimulator, AwsDevice
+from braket.aws import AwsDevice
from braket.circuits import Circuit, FreeParameter
+
def initialize_backend(backend_config):
- backend_options = backend_config['backend_options']
- simulator_type = backend_options.get('simulator_type', 'default')
- if simulator_type == 'default':
+ backend_options = backend_config["backend_options"]
+ simulator_type = backend_options.get("simulator_type", "default")
+ if simulator_type == "default":
return
AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")
else:
- print(f"Simulator type '{simulator_type}' is not supported in Amazon
Braket. Using default.")
+ print(
+ f"Simulator type '{simulator_type}' is not supported in Amazon
Braket. Using default."
+ )
return
AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")
+
def create_empty_circuit(num_qubits):
return Circuit()
+
def apply_not_gate(circuit, qubit_index):
circuit.x(qubit_index)
+
def apply_hadamard_gate(circuit, qubit_index):
circuit.h(qubit_index)
+
def apply_cnot_gate(circuit, control_qubit_index, target_qubit_index):
circuit.cnot(control_qubit_index, target_qubit_index)
-def apply_toffoli_gate(circuit, control_qubit_index1, control_qubit_index2,
target_qubit_index):
+
+def apply_toffoli_gate(
+ circuit, control_qubit_index1, control_qubit_index2, target_qubit_index
+):
circuit.ccnot(control_qubit_index1, control_qubit_index2,
target_qubit_index)
+
def apply_swap_gate(circuit, qubit_index1, qubit_index2):
circuit.swap(qubit_index1, qubit_index2)
+
def apply_pauli_x_gate(circuit, qubit_index):
circuit.x(qubit_index)
+
def apply_pauli_y_gate(circuit, qubit_index):
circuit.y(qubit_index)
+
def apply_pauli_z_gate(circuit, qubit_index):
circuit.z(qubit_index)
+
def execute_circuit(circuit, backend, backend_config):
- shots = backend_config['backend_options'].get('shots', 1)
+ shots = backend_config["backend_options"].get("shots", 1)
task = backend.run(circuit, shots=shots)
result = task.result()
return result.measurement_counts
+
# placeholder method for use in the testing suite
def get_final_state_vector(circuit, backend, backend_config):
- raise NotImplementedError("Final state vector calculation is not currently
supported with Amazon Braket.")
+ raise NotImplementedError(
+ "Final state vector calculation is not currently supported with Amazon
Braket."
+ )
+
def draw_circuit(circuit):
# Unfortunately, Amazon Braket does not have direct support for drawing
circuits in the same way
@@ -69,6 +88,7 @@ def draw_circuit(circuit):
# For simplicity, we'll print the circuit object which gives some textual
representation.
print(circuit)
+
def apply_rx_gate(circuit, qubit_index, angle):
if isinstance(angle, (int, float)):
circuit.rx(qubit_index, angle)
@@ -92,6 +112,7 @@ def apply_rz_gate(circuit, qubit_index, angle):
param = FreeParameter(angle)
circuit.rz(qubit_index, param)
+
def apply_u_gate(circuit, qubit_index, theta, phi, lambd):
circuit.rx(qubit_index, theta)
circuit.ry(qubit_index, phi)
diff --git a/qumat/cirq_backend.py b/qumat/cirq_backend.py
index 245edf445..f0c24dd1c 100644
--- a/qumat/cirq_backend.py
+++ b/qumat/cirq_backend.py
@@ -17,11 +17,16 @@
import cirq
import sympy
+
def initialize_backend(backend_config):
- # Assuming 'simulator_type' specifies the type of simulator in Cirq
- simulator_type = backend_config.get('backend_options',
{}).get('simulator_type', 'default')
- if simulator_type != 'default':
- print(f"Simulator type '{simulator_type}' is not supported in Cirq.
Ignoring this argument")
+ # Assuming 'simulator_type' specifies the type of simulator in Cirq
+ simulator_type = backend_config.get("backend_options", {}).get(
+ "simulator_type", "default"
+ )
+ if simulator_type != "default":
+ print(
+ f"Simulator type '{simulator_type}' is not supported in Cirq.
Ignoring this argument"
+ )
return cirq.Simulator()
@@ -29,38 +34,48 @@ def initialize_backend(backend_config):
def create_empty_circuit(num_qubits):
return cirq.Circuit()
+
def apply_not_gate(circuit, qubit_index):
qubit = cirq.LineQubit(qubit_index)
circuit.append(cirq.X(qubit))
+
def apply_hadamard_gate(circuit, qubit_index):
qubit = cirq.LineQubit(qubit_index)
circuit.append(cirq.H(qubit))
+
def apply_cnot_gate(circuit, control_qubit_index, target_qubit_index):
control_qubit = cirq.LineQubit(control_qubit_index)
target_qubit = cirq.LineQubit(target_qubit_index)
circuit.append(cirq.CNOT(control_qubit, target_qubit))
-def apply_toffoli_gate(circuit, control_qubit_index1, control_qubit_index2,
target_qubit_index):
+
+def apply_toffoli_gate(
+ circuit, control_qubit_index1, control_qubit_index2, target_qubit_index
+):
control_qubit1 = cirq.LineQubit(control_qubit_index1)
control_qubit2 = cirq.LineQubit(control_qubit_index2)
target_qubit = cirq.LineQubit(target_qubit_index)
circuit.append(cirq.CCX(control_qubit1, control_qubit2, target_qubit))
+
def apply_swap_gate(circuit, qubit_index1, qubit_index2):
qubit1 = cirq.LineQubit(qubit_index1)
qubit2 = cirq.LineQubit(qubit_index2)
circuit.append(cirq.SWAP(qubit1, qubit2))
+
def apply_pauli_x_gate(circuit, qubit_index):
qubit = cirq.LineQubit(qubit_index)
circuit.append(cirq.X(qubit))
+
def apply_pauli_y_gate(circuit, qubit_index):
qubit = cirq.LineQubit(qubit_index)
circuit.append(cirq.Y(qubit))
+
def apply_pauli_z_gate(circuit, qubit_index):
qubit = cirq.LineQubit(qubit_index)
circuit.append(cirq.Z(qubit))
@@ -69,21 +84,29 @@ def apply_pauli_z_gate(circuit, qubit_index):
def execute_circuit(circuit, backend, backend_config):
# Ensure measurement is added to capture the results
if not circuit.has_measurements():
- circuit.append(cirq.measure(*circuit.all_qubits(), key='result'))
+ circuit.append(cirq.measure(*circuit.all_qubits(), key="result"))
simulator = cirq.Simulator()
- parameter_values = backend_config.get('parameter_values', None)
+ parameter_values = backend_config.get("parameter_values", None)
if parameter_values:
# Convert parameter_values to applicable resolvers
res = [cirq.ParamResolver(parameter_values)]
- results = simulator.run_sweep(circuit,
repetitions=backend_config['backend_options'].get('shots', 1), params=res)
- return [result.histogram(key='result') for result in results]
+ results = simulator.run_sweep(
+ circuit,
+ repetitions=backend_config["backend_options"].get("shots", 1),
+ params=res,
+ )
+ return [result.histogram(key="result") for result in results]
else:
- result = simulator.run(circuit,
repetitions=backend_config['backend_options'].get('shots', 1))
- return [result.histogram(key='result')]
+ result = simulator.run(
+ circuit,
repetitions=backend_config["backend_options"].get("shots", 1)
+ )
+ return [result.histogram(key="result")]
+
def draw_circuit(circuit):
print(circuit)
+
def apply_rx_gate(circuit, qubit_index, angle):
param = sympy.Symbol(angle) if isinstance(angle, str) else angle
qubit = cirq.LineQubit(qubit_index)
@@ -101,6 +124,7 @@ def apply_rz_gate(circuit, qubit_index, angle):
qubit = cirq.LineQubit(qubit_index)
circuit.append(cirq.rz(param).on(qubit))
+
def apply_u_gate(circuit, qubit_index, theta, phi, lambd):
qubit = cirq.LineQubit(qubit_index)
circuit.append(cirq.rz(lambd).on(qubit))
diff --git a/qumat/qiskit_backend.py b/qumat/qiskit_backend.py
index 29fcb8aa4..a9800e658 100644
--- a/qumat/qiskit_backend.py
+++ b/qumat/qiskit_backend.py
@@ -16,10 +16,11 @@
#
import qiskit
+
def initialize_backend(backend_config):
- backend_options = backend_config['backend_options']
- simulator_type = backend_options['simulator_type']
- shots = backend_options['shots']
+ backend_options = backend_config["backend_options"]
+ simulator_type = backend_options["simulator_type"]
+ shots = backend_options["shots"]
backend = qiskit.Aer.get_backend(simulator_type)
backend.shots = shots
return backend
@@ -28,44 +29,51 @@ def initialize_backend(backend_config):
def create_empty_circuit(num_qubits):
return qiskit.QuantumCircuit(num_qubits)
+
def apply_not_gate(circuit, qubit_index):
# Apply a NOT gate (X gate) on the specified qubit
circuit.x(qubit_index)
+
def apply_hadamard_gate(circuit, qubit_index):
# Apply a Hadamard gate on the specified qubit
circuit.h(qubit_index)
+
def apply_cnot_gate(circuit, control_qubit_index, target_qubit_index):
# Apply a CNOT gate (controlled-X gate) with the specified control and
# target qubits
circuit.cx(control_qubit_index, target_qubit_index)
-def apply_toffoli_gate(circuit, control_qubit_index1,
- control_qubit_index2,
- target_qubit_index):
+
+def apply_toffoli_gate(
+ circuit, control_qubit_index1, control_qubit_index2, target_qubit_index
+):
# Apply a Toffoli gate (controlled-controlled-X gate) with the
# specified control and target qubits
- circuit.ccx(control_qubit_index1,
- control_qubit_index2,
- target_qubit_index)
+ circuit.ccx(control_qubit_index1, control_qubit_index2, target_qubit_index)
+
def apply_swap_gate(circuit, qubit_index1, qubit_index2):
# Apply a SWAP gate to exchange the states of two qubits
circuit.swap(qubit_index1, qubit_index2)
+
def apply_pauli_x_gate(circuit, qubit_index):
# Apply a Pauli X gate on the specified qubit
circuit.x(qubit_index)
+
def apply_pauli_y_gate(circuit, qubit_index):
# Apply a Pauli Y gate on the specified qubit
circuit.y(qubit_index)
+
def apply_pauli_z_gate(circuit, qubit_index):
# Apply a Pauli Z gate on the specified qubit
circuit.z(qubit_index)
+
def execute_circuit(circuit, backend, backend_config):
# Add measurements if they are not already present
if not circuit.cregs:
@@ -74,21 +82,29 @@ def execute_circuit(circuit, backend, backend_config):
# Ensure the circuit is parameterized properly
if circuit.parameters:
# Parse the global parameter configuration
- parameter_bindings = {param:
backend_config['parameter_values'][str(param)] for param in circuit.parameters}
+ parameter_bindings = {
+ param: backend_config["parameter_values"][str(param)]
+ for param in circuit.parameters
+ }
transpiled_circuit = qiskit.transpile(circuit, backend)
bound_circuit =
transpiled_circuit.assign_parameters(parameter_bindings)
- job = backend.run(bound_circuit,
shots=backend_config['backend_options']['shots'])
+ job = backend.run(
+ bound_circuit, shots=backend_config["backend_options"]["shots"]
+ )
result = job.result()
return result.get_counts()
else:
transpiled_circuit = qiskit.transpile(circuit, backend)
- job = backend.run(transpiled_circuit,
shots=backend_config['backend_options']['shots'])
+ job = backend.run(
+ transpiled_circuit,
shots=backend_config["backend_options"]["shots"]
+ )
result = job.result()
return result.get_counts()
+
# placeholder method for use in the testing suite
def get_final_state_vector(circuit, backend, backend_config):
- simulator = qiskit.Aer.get_backend('statevector_simulator')
+ simulator = qiskit.Aer.get_backend("statevector_simulator")
# Simulate the circuit
transpiled_circuit = qiskit.transpile(circuit, simulator)
@@ -97,22 +113,27 @@ def get_final_state_vector(circuit, backend,
backend_config):
return result.get_statevector()
+
def draw_circuit(circuit):
# Use Qiskit's built-in drawing function
print(circuit.draw())
+
def apply_rx_gate(circuit, qubit_index, angle):
param = qiskit.circuit.Parameter(angle) if isinstance(angle, str) else
angle
circuit.rx(param, qubit_index)
+
def apply_ry_gate(circuit, qubit_index, angle):
param = qiskit.circuit.Parameter(angle) if isinstance(angle, str) else
angle
circuit.ry(param, qubit_index)
+
def apply_rz_gate(circuit, qubit_index, angle):
param = qiskit.circuit.Parameter(angle) if isinstance(angle, str) else
angle
circuit.rz(param, qubit_index)
+
def apply_u_gate(circuit, qubit_index, theta, phi, lambd):
# Apply the U gate directly with specified parameters
circuit.u(theta, phi, lambd, qubit_index)
diff --git a/qumat/qumat.py b/qumat/qumat.py
index db0dc1952..4d368d44c 100644
--- a/qumat/qumat.py
+++ b/qumat/qumat.py
@@ -16,11 +16,14 @@
#
from importlib import import_module
+
class QuMat:
def __init__(self, backend_config):
self.backend_config = backend_config
- self.backend_name = backend_config['backend_name']
- self.backend_module = import_module(f".{self.backend_name}_backend",
package="qumat")
+ self.backend_name = backend_config["backend_name"]
+ self.backend_module = import_module(
+ f".{self.backend_name}_backend", package="qumat"
+ )
self.backend = self.backend_module.initialize_backend(backend_config)
self.circuit = None
self.parameters = {}
@@ -35,10 +38,16 @@ class QuMat:
self.backend_module.apply_hadamard_gate(self.circuit, qubit_index)
def apply_cnot_gate(self, control_qubit_index, target_qubit_index):
- self.backend_module.apply_cnot_gate(self.circuit, control_qubit_index,
target_qubit_index)
+ self.backend_module.apply_cnot_gate(
+ self.circuit, control_qubit_index, target_qubit_index
+ )
- def apply_toffoli_gate(self, control_qubit_index1, control_qubit_index2,
target_qubit_index):
- self.backend_module.apply_toffoli_gate(self.circuit,
control_qubit_index1, control_qubit_index2, target_qubit_index)
+ def apply_toffoli_gate(
+ self, control_qubit_index1, control_qubit_index2, target_qubit_index
+ ):
+ self.backend_module.apply_toffoli_gate(
+ self.circuit, control_qubit_index1, control_qubit_index2,
target_qubit_index
+ )
def apply_swap_gate(self, qubit_index1, qubit_index2):
self.backend_module.apply_swap_gate(self.circuit, qubit_index1,
qubit_index2)
@@ -55,8 +64,10 @@ class QuMat:
def execute_circuit(self, parameter_values=None):
if parameter_values:
self.bind_parameters(parameter_values)
- self.backend_config['parameter_values'] = self.parameters # Pass
parameters
- return self.backend_module.execute_circuit(self.circuit, self.backend,
self.backend_config)
+ self.backend_config["parameter_values"] = self.parameters # Pass
parameters
+ return self.backend_module.execute_circuit(
+ self.circuit, self.backend, self.backend_config
+ )
def bind_parameters(self, parameter_values):
for param, value in parameter_values.items():
@@ -65,7 +76,9 @@ class QuMat:
# placeholder method for use in the testing suite
def get_final_state_vector(self):
- return self.backend_module.get_final_state_vector(self.circuit,
self.backend, self.backend_config)
+ return self.backend_module.get_final_state_vector(
+ self.circuit, self.backend, self.backend_config
+ )
def draw(self):
return self.backend_module.draw_circuit(self.circuit)
diff --git a/testing/qiskit_helpers.py b/testing/qiskit_helpers.py
index 154b7f3ee..fd40a9767 100644
--- a/testing/qiskit_helpers.py
+++ b/testing/qiskit_helpers.py
@@ -19,15 +19,13 @@
from qiskit import Aer, QuantumCircuit, transpile
from qiskit.quantum_info import Statevector
+
def get_qumat_backend_config(test_type: str = "get_final_state_vector"):
if test_type == "get_final_state_vector":
print("success")
qumat_backend_config = {
- 'backend_name': 'qiskit',
- 'backend_options': {
- 'simulator_type': 'statevector_simulator',
- 'shots': 1
- }
+ "backend_name": "qiskit",
+ "backend_options": {"simulator_type": "statevector_simulator",
"shots": 1},
}
else:
pass
@@ -35,11 +33,15 @@ def get_qumat_backend_config(test_type: str =
"get_final_state_vector"):
return qumat_backend_config
-def get_native_example_final_state_vector(initial_state_ket_str: str = "000")
-> Statevector:
+def get_native_example_final_state_vector(
+ initial_state_ket_str: str = "000",
+) -> Statevector:
n_qubits = len(initial_state_ket_str)
- assert n_qubits == 3, print("The current qiskit native testing example is
strictly 3 qubits")
+ assert n_qubits == 3, print(
+ "The current qiskit native testing example is strictly 3 qubits"
+ )
- simulator = Aer.get_backend('statevector_simulator')
+ simulator = Aer.get_backend("statevector_simulator")
qc = QuantumCircuit(n_qubits)
diff --git a/testing/qumat_helpers.py b/testing/qumat_helpers.py
index c11329e6d..c01bf6580 100644
--- a/testing/qumat_helpers.py
+++ b/testing/qumat_helpers.py
@@ -18,19 +18,21 @@ import numpy as np
from functools import reduce
from qumat.qumat import QuMat
+
class BinaryString(str):
def __new__(cls, value):
- if not all(char in ['0', '1'] for char in value):
+ if not all(char in ["0", "1"] for char in value):
raise ValueError("String contains characters other than '0' and
'1'")
return str.__new__(cls, value)
-def create_np_computational_basis_state(ket_str: BinaryString,
- np_dtype: str = "complex128") ->
np.array:
+def create_np_computational_basis_state(
+ ket_str: BinaryString, np_dtype: str = "complex128"
+) -> np.array:
single_qubit_state_dict = {
- "0": np.array([1, 0], dtype=np_dtype),
- "1": np.array([0, 1], dtype=np_dtype)
- }
+ "0": np.array([1, 0], dtype=np_dtype),
+ "1": np.array([0, 1], dtype=np_dtype),
+ }
single_qubit_vectors = map(single_qubit_state_dict.get, ket_str)
computational_basis_vector = reduce(np.kron, single_qubit_vectors)
@@ -38,9 +40,13 @@ def create_np_computational_basis_state(ket_str:
BinaryString,
return computational_basis_vector
-def get_qumat_example_final_state_vector(backend_config: dict,
initial_state_ket_str: BinaryString = "000"):
+def get_qumat_example_final_state_vector(
+ backend_config: dict, initial_state_ket_str: BinaryString = "000"
+):
n_qubits = len(initial_state_ket_str)
- assert n_qubits == 3, print("The current qumat testing example is strictly
3 qubits")
+ assert n_qubits == 3, print(
+ "The current qumat testing example is strictly 3 qubits"
+ )
qumat_instance = QuMat(backend_config)
diff --git a/testing/test_final_quantum_states.py
b/testing/test_final_quantum_states.py
index af4daa9b0..aeda2cd0c 100644
--- a/testing/test_final_quantum_states.py
+++ b/testing/test_final_quantum_states.py
@@ -18,6 +18,7 @@ from qumat_helpers import get_qumat_example_final_state_vector
import numpy as np
from importlib import import_module
+
def test_final_state_vector():
# Specify initial computational basis state vector
initial_ket_str = "001"
@@ -26,12 +27,17 @@ def test_final_state_vector():
for backend_name in backends_to_test:
backend_module = import_module(f"{backend_name}_helpers",
package="qumat")
# use native implementation
- native_example_vector =
backend_module.get_native_example_final_state_vector(initial_ket_str)
+ native_example_vector =
backend_module.get_native_example_final_state_vector(
+ initial_ket_str
+ )
# use qumat implementation
- qumat_backend_config =
backend_module.get_qumat_backend_config("get_final_state_vector")
- qumat_example_vector =
get_qumat_example_final_state_vector(qumat_backend_config, initial_ket_str)
+ qumat_backend_config = backend_module.get_qumat_backend_config(
+ "get_final_state_vector"
+ )
+ qumat_example_vector = get_qumat_example_final_state_vector(
+ qumat_backend_config, initial_ket_str
+ )
# Compare final state vectors from qumat vs. native implementation
np.testing.assert_array_equal(qumat_example_vector,
native_example_vector)
-