From fa28bb23d3c4a8627dbe9cdfb8cb259ba2b48e09 Mon Sep 17 00:00:00 2001 From: "Guan Ming(Wesley) Chiu" <105915352+guan404ming@users.noreply.github.com> Date: Wed, 15 Oct 2025 17:45:46 +0800 Subject: [PATCH 1/2] Refactor create_empty_circuit to handle num_qubits --- qumat/amazon_braket_backend.py | 8 ++- qumat/cirq_backend.py | 9 +++- qumat/qiskit_backend.py | 7 ++- qumat/qumat.py | 2 +- testing/test_create_circuit.py | 93 ++++++++++++++++++++++++++++++++++ 5 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 testing/test_create_circuit.py diff --git a/qumat/amazon_braket_backend.py b/qumat/amazon_braket_backend.py index 3ea9e84129..20cfff2549 100644 --- a/qumat/amazon_braket_backend.py +++ b/qumat/amazon_braket_backend.py @@ -33,8 +33,12 @@ def initialize_backend(backend_config): return AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1") -def create_empty_circuit(num_qubits): - return Circuit() +def create_empty_circuit(num_qubits=None): + circuit = Circuit() + if num_qubits is not None: + for i in range(num_qubits): + circuit.i(i) + return circuit def apply_not_gate(circuit, qubit_index): diff --git a/qumat/cirq_backend.py b/qumat/cirq_backend.py index 81661ee641..8294bfc068 100644 --- a/qumat/cirq_backend.py +++ b/qumat/cirq_backend.py @@ -31,8 +31,13 @@ def initialize_backend(backend_config): return cirq.Simulator() -def create_empty_circuit(num_qubits): - return cirq.Circuit() +def create_empty_circuit(num_qubits=None): + circuit = cirq.Circuit() + if num_qubits is not None: + qubits = [cirq.LineQubit(i) for i in range(num_qubits)] + for qubit in qubits: + circuit.append(cirq.I(qubit)) + return circuit def apply_not_gate(circuit, qubit_index): diff --git a/qumat/qiskit_backend.py b/qumat/qiskit_backend.py index ec839bf8de..198fcbfed6 100644 --- a/qumat/qiskit_backend.py +++ b/qumat/qiskit_backend.py @@ -27,8 +27,11 @@ def initialize_backend(backend_config): return backend -def create_empty_circuit(num_qubits): - return qiskit.QuantumCircuit(num_qubits) +def create_empty_circuit(num_qubits=None): + if num_qubits is not None: + return qiskit.QuantumCircuit(num_qubits) + else: + return qiskit.QuantumCircuit() def apply_not_gate(circuit, qubit_index): diff --git a/qumat/qumat.py b/qumat/qumat.py index 395fb934bb..cdfe788479 100644 --- a/qumat/qumat.py +++ b/qumat/qumat.py @@ -28,7 +28,7 @@ def __init__(self, backend_config): self.circuit = None self.parameters = {} - def create_empty_circuit(self, num_qubits): + def create_empty_circuit(self, num_qubits=None): self.circuit = self.backend_module.create_empty_circuit(num_qubits) def apply_not_gate(self, qubit_index): diff --git a/testing/test_create_circuit.py b/testing/test_create_circuit.py new file mode 100644 index 0000000000..8fb1d43446 --- /dev/null +++ b/testing/test_create_circuit.py @@ -0,0 +1,93 @@ +# +# 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. +# + +import pytest + +from .conftest import TESTING_BACKENDS +from qumat import QuMat + + +class TestCreateCircuit: + """Test class for create_empty_circuit functionality.""" + + def get_backend_config(self, backend_name): + """Helper method to get backend configuration.""" + if backend_name == "qiskit": + return { + "backend_name": backend_name, + "backend_options": { + "simulator_type": "aer_simulator", + "shots": 1000, + }, + } + elif backend_name == "cirq": + return { + "backend_name": backend_name, + "backend_options": { + "simulator_type": "default", + "shots": 1000, + }, + } + elif backend_name == "amazon_braket": + return { + "backend_name": backend_name, + "backend_options": { + "simulator_type": "local", + "shots": 1000, + }, + } + + @pytest.mark.parametrize("backend_name", TESTING_BACKENDS) + def test_create_empty_circuit(self, backend_name): + """Test that create_empty_circuit works""" + backend_config = self.get_backend_config(backend_name) + qumat = QuMat(backend_config) + qumat.create_empty_circuit() + + assert qumat.circuit is not None + + @pytest.mark.parametrize("backend_name", TESTING_BACKENDS) + @pytest.mark.parametrize("num_qubits", [1, 3, 5]) + def test_create_circuit_initializes_to_zero(self, backend_name, num_qubits): + """Test that create_empty_circuit properly initializes all qubits to |0⟩.""" + backend_config = self.get_backend_config(backend_name) + qumat = QuMat(backend_config) + + # Create circuit with specified number of qubits + qumat.create_empty_circuit(num_qubits) + + # Execute and verify all qubits measure |0⟩ + results = qumat.execute_circuit() + if isinstance(results, list): + results = results[0] + + total_shots = sum(results.values()) + assert total_shots > 0 + + # Find count for all-zeros state + zero_state_count = 0 + for state, count in results.items(): + if isinstance(state, str): + if state == "0" * num_qubits: + zero_state_count = count + else: + if state == 0: + zero_state_count = count + + assert zero_state_count > 0.95 * total_shots, ( + f"Expected |0...0⟩ state, got {zero_state_count}/{total_shots}" + ) From 5b52c2cfa1791b0b41e9d286404dc811fc1ae27d Mon Sep 17 00:00:00 2001 From: "Guan-Ming (Wesley) Chiu" <105915352+guan404ming@users.noreply.github.com> Date: Mon, 20 Oct 2025 15:06:55 +0800 Subject: [PATCH 2/2] Update type annotation --- qumat/amazon_braket_backend.py | 2 +- qumat/cirq_backend.py | 2 +- qumat/qiskit_backend.py | 2 +- qumat/qumat.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qumat/amazon_braket_backend.py b/qumat/amazon_braket_backend.py index 20cfff2549..984d3fbea8 100644 --- a/qumat/amazon_braket_backend.py +++ b/qumat/amazon_braket_backend.py @@ -33,7 +33,7 @@ def initialize_backend(backend_config): return AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1") -def create_empty_circuit(num_qubits=None): +def create_empty_circuit(num_qubits: int | None = None): circuit = Circuit() if num_qubits is not None: for i in range(num_qubits): diff --git a/qumat/cirq_backend.py b/qumat/cirq_backend.py index 8294bfc068..2ba5cb2cf4 100644 --- a/qumat/cirq_backend.py +++ b/qumat/cirq_backend.py @@ -31,7 +31,7 @@ def initialize_backend(backend_config): return cirq.Simulator() -def create_empty_circuit(num_qubits=None): +def create_empty_circuit(num_qubits: int | None = None): circuit = cirq.Circuit() if num_qubits is not None: qubits = [cirq.LineQubit(i) for i in range(num_qubits)] diff --git a/qumat/qiskit_backend.py b/qumat/qiskit_backend.py index 198fcbfed6..67043c4b07 100644 --- a/qumat/qiskit_backend.py +++ b/qumat/qiskit_backend.py @@ -27,7 +27,7 @@ def initialize_backend(backend_config): return backend -def create_empty_circuit(num_qubits=None): +def create_empty_circuit(num_qubits: int | None = None): if num_qubits is not None: return qiskit.QuantumCircuit(num_qubits) else: diff --git a/qumat/qumat.py b/qumat/qumat.py index cdfe788479..3725db1e28 100644 --- a/qumat/qumat.py +++ b/qumat/qumat.py @@ -28,7 +28,7 @@ def __init__(self, backend_config): self.circuit = None self.parameters = {} - def create_empty_circuit(self, num_qubits=None): + def create_empty_circuit(self, num_qubits: int | None = None): self.circuit = self.backend_module.create_empty_circuit(num_qubits) def apply_not_gate(self, qubit_index):