Skip to content

Commit 999d97e

Browse files
committed
fixed bug in construction of observable detectors
1 parent 50c9376 commit 999d97e

File tree

1 file changed

+71
-48
lines changed

1 file changed

+71
-48
lines changed

pygsti/extras/dem_construction/pygsti_object_builders.py

Lines changed: 71 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -113,43 +113,43 @@ def create_processor_spec(pcircuit, qubit_labels, gates=['Gcnot','Gh']):
113113

114114
return pspec
115115

116-
def build_model(error_rates, pspec):
117-
"""
118-
Creates a *spatially homogeneous* error model from
119-
the given error rates dictionary. Could easily be generalized to
120-
spatially inhomogeneous errors. Works only for a
121-
gate set of only Gh and Gcnot.
122-
"""
123-
######TODO: GENERALIZE TO OTHER MODELS########
124-
oneQ_gate_names = ['Gh', ]
125-
twoQ_gate_names = ['Gcnot', ]
126-
gate_dictionary = dict()
116+
# def build_model(error_rates, pspec):
117+
# """
118+
# Creates a *spatially homogeneous* error model from
119+
# the given error rates dictionary. Could easily be generalized to
120+
# spatially inhomogeneous errors. Works only for a
121+
# gate set of only Gh and Gcnot.
122+
# """
123+
# ######TODO: GENERALIZE TO OTHER MODELS########
124+
# oneQ_gate_names = ['Gh', ]
125+
# twoQ_gate_names = ['Gcnot', ]
126+
# gate_dictionary = dict()
127127

128128

129-
def create_gate_object(erates, num_qubits, gate_name):
130-
state_space = QubitSpace(num_qubits)
131-
lindblad_errorgen = LindbladErrorgen.from_elementary_errorgens(erates,
132-
state_space=state_space,
133-
evotype='stabilizer')
134-
perfect_gate = StaticCliffordOp(pspec.gate_unitaries[gate_name], evotype='stabilizer')
135-
exp_errorgen = ExpErrorgenOp(lindblad_errorgen)
136-
gate_mm = ComposedOp([perfect_gate, exp_errorgen])
137-
return gate_mm
129+
# def create_gate_object(erates, num_qubits, gate_name):
130+
# state_space = QubitSpace(num_qubits)
131+
# lindblad_errorgen = LindbladErrorgen.from_elementary_errorgens(erates,
132+
# state_space=state_space,
133+
# evotype='stabilizer')
134+
# perfect_gate = StaticCliffordOp(pspec.gate_unitaries[gate_name], evotype='stabilizer')
135+
# exp_errorgen = ExpErrorgenOp(lindblad_errorgen)
136+
# gate_mm = ComposedOp([perfect_gate, exp_errorgen])
137+
# return gate_mm
138138

139-
for i, gate_name in enumerate(oneQ_gate_names):
140-
for j, q in enumerate(pspec.qubit_labels):
141-
label = pygsti.baseobjs.label.Label(gate_name, q)
142-
gate_dictionary[label] = create_gate_object(error_rates[gate_name], 1, gate_name)
143-
144-
for i, gate_name in enumerate(twoQ_gate_names):
145-
for j, qs in enumerate(pspec.availability[gate_name]):
146-
label = pygsti.baseobjs.label.Label(gate_name, qs)
147-
gate_dictionary[label] = create_gate_object(error_rates[gate_name], 2, gate_name)
139+
# for i, gate_name in enumerate(oneQ_gate_names):
140+
# for j, q in enumerate(pspec.qubit_labels):
141+
# label = pygsti.baseobjs.label.Label(gate_name, q)
142+
# gate_dictionary[label] = create_gate_object(error_rates[gate_name], 1, gate_name)
143+
144+
# for i, gate_name in enumerate(twoQ_gate_names):
145+
# for j, qs in enumerate(pspec.availability[gate_name]):
146+
# label = pygsti.baseobjs.label.Label(gate_name, qs)
147+
# gate_dictionary[label] = create_gate_object(error_rates[gate_name], 2, gate_name)
148148

149-
prep_layers = None
150-
povm_layers = None
151-
model = LocalNoiseModel(pspec, gate_dictionary, prep_layers, povm_layers, evotype='stabilizer')
152-
return model
149+
# prep_layers = None
150+
# povm_layers = None
151+
# model = LocalNoiseModel(pspec, gate_dictionary, prep_layers, povm_layers, evotype='stabilizer')
152+
# return model
153153

154154
import numpy as np
155155
import stim
@@ -264,7 +264,7 @@ def create_processor_spec(pcircuit, qubit_labels, gates=['Gcnot','Gh']):
264264
# Find all the CNOT gates used in the circuit, using brute force string comprehension
265265
cleaned_pcstr = pyg_cstr.replace(']', '').replace('[', '').split('@')[0]
266266
connections = [(int(s.split(':')[1]), int(s.split(':')[2])) for s in cleaned_pcstr.split('G') if len(s.split(':')) > 2]
267-
availability={'Gcnot':connections}
267+
availability={'Gcnot':connections, 'Gcphase':connections}
268268
pspec = pygsti.processors.QubitProcessorSpec(len(qubit_labels), gates, qubit_labels=qubit_labels,
269269
availability=availability)
270270

@@ -338,7 +338,7 @@ def parse_pauli_product(prod, current_qubit_mapping):
338338
return (pauli_string, qubits)
339339

340340

341-
def stim_to_pygsti_circuit(circuit, qubit_labels, qubit_relabelling_dict=None, show_qubit_mappings=False, include_observables=False, include_idles=False):
341+
def stim_to_pygsti_circuit(circuit, qubit_labels, qubit_relabelling_dict=None, show_qubit_mappings=False, include_observables=False, separate_observables=False, include_idles=False):
342342

343343
if qubit_relabelling_dict is None:
344344
qubit_relabelling_dict = {q:q for q in qubit_labels}
@@ -347,6 +347,7 @@ def stim_to_pygsti_circuit(circuit, qubit_labels, qubit_relabelling_dict=None, s
347347

348348
measurements = []
349349
detectors = []
350+
observable_detectors = []
350351

351352
def convert_1q_layer(gatename, stim_layer_string, current_qubit_mapping):
352353
gate_dict= {'H':'Gh',
@@ -437,19 +438,35 @@ def update_qubit_mapping(line, current_qubit_mapping, qubit_labels):
437438
targ = len(measurements)-1*rel_meas
438439
det.append(targ)
439440
detectors.append(det)
441+
# elif 'OBSERVABLE_INCLUDE' in line.split('(')[0]:
442+
# if not include_observables:
443+
# pass
444+
# else:
445+
# #TODO PROPERLY EXTRACT THE LABEL OF THE OBSERVABLE
446+
# #print(line)
447+
# det = []
448+
# for arg in line.split(' ')[1:]:
449+
# #get the ref number, it's negative, index into measurements
450+
# if 'rec' in arg:
451+
# rel_meas = int(re.findall(r'\[-(\d+)\]', arg)[0])
452+
# targ = len(measurements)-1*rel_meas
453+
# det.append(targ)
454+
# detectors.append(det)
440455
elif 'OBSERVABLE_INCLUDE' in line.split('(')[0]:
441-
if not include_observables:
442-
pass
443-
else:
444-
#print(line)
445-
det = []
446-
for arg in line.split(' ')[1:]:
447-
#get the ref number, it's negative, index into measurements
448-
if 'rec' in arg:
449-
rel_meas = int(re.findall(r'\[-(\d+)\]', arg)[0])
450-
targ = len(measurements)-1*rel_meas
451-
det.append(targ)
452-
detectors.append(det)
456+
if include_observables:
457+
# Extract the integer j from OBSERVABLE_INCLUDE(j)
458+
match = re.search(r'OBSERVABLE_INCLUDE\((\d+)\)', line)
459+
if match:
460+
j = int(match.group(1))
461+
if len(observable_detectors) <= j:
462+
observable_detectors.append([])
463+
# Extract measurement references from the line
464+
for arg in line.split(' ')[1:]:
465+
if 'rec' in arg:
466+
rel_meas = int(re.findall(r'\[-(\d+)\]', arg)[0])
467+
targ = len(measurements) - 1 * rel_meas
468+
observable_detectors[j].append(targ)
469+
453470
elif 'TICK' in line.split(' ') or 'QUBIT_COORDS' or 'SHIFT_COORDS' in line.split(' '):
454471
pass
455472
else:
@@ -458,5 +475,11 @@ def update_qubit_mapping(line, current_qubit_mapping, qubit_labels):
458475
pyg_c = pygsti.circuits.Circuit(''.join(gate_layers)+'@(' + ','.join([str(q) for q in range(1+max(current_qubit_mapping.values()))]) + ')', editable=True)
459476
pyg_c.delete_idle_layers_inplace()
460477
pyg_c.done_editing()
478+
479+
if not separate_observables:
480+
detectors.extend(observable_detectors)
481+
482+
return pyg_c, current_qubit_mapping, measurements, detectors
461483

462-
return pyg_c, current_qubit_mapping, measurements, detectors
484+
else:
485+
return pyg_c, current_qubit_mapping, measurements, detectors, observable_detectors

0 commit comments

Comments
 (0)