Skip to content

Commit 5533766

Browse files
committed
For cudaq execution, implement improved gate count/depth computation
1 parent 8e3e76c commit 5533766

File tree

1 file changed

+60
-9
lines changed

1 file changed

+60
-9
lines changed

_common/cudaq/execute.py

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import time
2727
import copy
2828
import json
29+
import math
2930

3031
from _common import qcb_mpi as mpi
3132
from _common import metrics
@@ -229,6 +230,8 @@ def execute_circuit (batched_circuit):
229230
# Initiate execution
230231
circuit = batched_circuit["qc"]
231232

233+
############
234+
232235
# create a pseudo-job to perform metrics processing upon return
233236
job = Job()
234237

@@ -273,18 +276,15 @@ def execute_circuit (batched_circuit):
273276

274277
# ***********************************
275278

276-
# store circuit dimensional metrics
277-
# DEVNOTE: this is not accurate; it is provided so the volumetric plots show something
278-
279-
# compute depth and gate counts based on number of qubits
279+
# number of qubits is stored in the "group" field
280280
qc_size = int(active_circuit["group"])
281-
qc_depth = 4 * pow(qc_size, 2)
282-
283-
qc_xi = 0.5
284-
285-
qc_n2q = int(qc_depth * 0.75)
281+
282+
# obtain initial circuit metrics
283+
qc_depth, qc_size, qc_count_ops, qc_xi, qc_n2q = get_circuit_metrics(circuit, qc_size)
284+
286285
qc_tr_depth = qc_depth
287286
qc_tr_size = qc_size
287+
qc_tr_count_ops = qc_count_ops
288288
qc_tr_xi = qc_xi
289289
qc_tr_n2q = qc_n2q
290290

@@ -302,6 +302,57 @@ def execute_circuit (batched_circuit):
302302
##############
303303
# Here we complete the job immediately
304304
job_complete(job)
305+
306+
307+
# Get circuit metrics fom the circuit passed in
308+
def get_circuit_metrics(qc, qc_size):
309+
310+
# get resource info from cudaq
311+
resources = cudaq.estimate_resources(qc[0], *qc[1])
312+
resources_str = str(resources)
313+
314+
import re
315+
316+
# Get total gates (not needed as we use the .count() function)
317+
#total_match = re.search(r'Total # of gates:\s*(\d+)', resources_str)
318+
#total_gates = int(total_match.group(1)) if total_match else 0
319+
320+
total_gates = resources.count()
321+
322+
# the resources object returned is not a dict; need to parse the string to get 2q gates
323+
# Get all gate counts that start with 'c' (controlled/2-qubit gates)
324+
two_qubit_gates = 0
325+
for line in resources_str.split('\n'):
326+
match = re.match(r'\s*(c\w+)\s*:\s*(\d+)', line)
327+
if match:
328+
two_qubit_gates += int(match.group(2))
329+
330+
# print(f"Total: {total_gates}, 2-qubit: {two_qubit_gates}")
331+
332+
qc_depth = estimate_depth(qc_size, total_gates, two_qubit_gates)
333+
#print(qc_depth)
334+
335+
qc_xi = two_qubit_gates / max(total_gates, 1)
336+
qc_n2q = two_qubit_gates
337+
338+
qc_count_ops = total_gates
339+
340+
return qc_depth, qc_size, qc_count_ops, qc_xi, qc_n2q
341+
342+
# Make estimate of circuit depth using heuristic approach
343+
def estimate_depth(num_qubits, total_gates, two_qubit_gates):
344+
N = num_qubits
345+
K = two_qubit_gates
346+
S = total_gates - K
347+
348+
# Theoretical minimum (perfect packing - 2Qs and 1Qs and MZ)
349+
depth_min = math.ceil(2*K / N) + math.ceil(S / N) + 1
350+
351+
# Realistic estimate (assume 40% packing efficiency)
352+
depth_estimate = depth_min * 2.5
353+
354+
return depth_estimate
355+
305356

306357
# klunky way to know the last group executed
307358
last_group = None

0 commit comments

Comments
 (0)