Skip to content

Commit 1a6b6d4

Browse files
authored
Merge pull request #828 from SRI-International/tl/refactor-packaging
Check in missing execute_parallel for qiskit
2 parents 0770a6f + fe372b4 commit 1a6b6d4

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

qedclib/qiskit/execute_parallel.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# (C) Quantum Economic Development Consortium (QED-C) 2024.
2+
# Technical Advisory Committee on Standards and Benchmarks (TAC)
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http:#www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
###############################################################################
17+
# Parallel Execution Module - Qiskit (EXPERIMENTAL)
18+
#
19+
# Maps multiple circuits onto disjoint qubit regions of a single QPU
20+
# for parallel execution, then decomposes results back to per-circuit counts.
21+
#
22+
# This module is loaded lazily from execute.py when parallel_execution is True.
23+
# It accesses execute module state (sampler, backend, noise, etc.) via
24+
# "import execute as ex".
25+
###############################################################################
26+
27+
def execute_circuits_parallel(circuits, num_shots):
28+
"""
29+
Execute circuits in parallel by mapping onto disjoint qubit regions of the QPU.
30+
31+
When the real implementation is in place, this function will:
32+
1. Compose multiple circuits onto disjoint qubit subsets of a single large circuit
33+
2. Submit the composed circuit as one job
34+
3. Decompose the combined results back to per-circuit counts
35+
36+
Currently a stub that calls back to execute_circuits() sequentially.
37+
Replace the stub section below with the real implementation
38+
(e.g., Qiskit ParallelExperiment or QuantumCircuit.compose() + initial_layout).
39+
40+
Args:
41+
circuits: list of QuantumCircuit objects
42+
num_shots: shots per circuit (all circuits share the same shot count)
43+
44+
Returns:
45+
(job_id, ExecutionResult) tuple, same as execute_circuits()
46+
"""
47+
import execute as ex
48+
49+
if ex.verbose:
50+
print(f"... execute_circuits_parallel: {len(circuits)} circuits, {num_shots} shots")
51+
52+
#######################################################################
53+
# STUB: replace this section with the real parallel implementation.
54+
# The code below simply calls execute_circuits() sequentially.
55+
# It temporarily disables parallel_execution to avoid recursion
56+
# back into this function.
57+
#######################################################################
58+
print(f">>> execute_circuits_parallel [qiskit]: {len(circuits)} circuits, {num_shots} shots")
59+
print(f"... [STUB] parallel qubit mapping not yet implemented, executing sequentially")
60+
61+
ex.parallel_execution = False
62+
try:
63+
result = ex.execute_circuits(circuits, num_shots)
64+
finally:
65+
ex.parallel_execution = True
66+
67+
return result
68+
69+
70+
def execute_circuit_groups_parallel(circuit_groups, num_shots_list):
71+
"""
72+
Execute circuit groups in parallel by mapping circuits from multiple groups
73+
onto disjoint qubit regions of a single QPU.
74+
75+
When the real implementation is in place, this function will:
76+
1. Determine qubit allocation per group (based on max circuit width in group)
77+
2. For groups with the same shot count: compose one circuit from each group
78+
onto disjoint qubit regions and submit as a single job
79+
3. For groups with different shot counts: batch same-shot groups together,
80+
execute each batch as above
81+
4. Decompose combined results back to per-group, per-circuit counts
82+
83+
Qubit allocation uses the widest circuit in each group to determine that
84+
group's region. Narrower circuits within a group use a subset of the
85+
allocated qubits.
86+
87+
Currently a stub that calls back to execute_circuit_groups() sequentially.
88+
Replace the stub section below with the real implementation.
89+
90+
Args:
91+
circuit_groups: list of lists of QuantumCircuit objects
92+
num_shots_list: list of ints, one per group
93+
94+
Returns:
95+
(job_id, group_results) tuple:
96+
- job_id: identifier for the job
97+
- group_results: list of ExecutionResult, one per group
98+
"""
99+
import execute as ex
100+
101+
if ex.verbose:
102+
group_sizes = [len(g) for g in circuit_groups]
103+
print(f"... execute_circuit_groups_parallel: {len(circuit_groups)} groups, "
104+
f"sizes={group_sizes}, shots={num_shots_list}")
105+
106+
#######################################################################
107+
# STUB: replace this section with the real parallel implementation.
108+
# The code below calls execute_circuit_groups() sequentially.
109+
# It temporarily disables parallel_execution to avoid recursion
110+
# back into this function.
111+
#######################################################################
112+
print(f">>> execute_circuit_groups_parallel [qiskit]: {len(circuit_groups)} groups")
113+
print(f"... [STUB] parallel group execution not yet implemented, executing sequentially")
114+
115+
ex.parallel_execution = False
116+
try:
117+
result = ex.execute_circuit_groups(circuit_groups, num_shots_list=num_shots_list)
118+
finally:
119+
ex.parallel_execution = True
120+
121+
return result

0 commit comments

Comments
 (0)