Skip to content

Commit

Permalink
DFE algorithm and protocol added
Browse files Browse the repository at this point in the history
  • Loading branch information
tjproct committed Oct 22, 2024
1 parent eacea59 commit a7da8db
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 0 deletions.
2 changes: 2 additions & 0 deletions pygsti/algorithms/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@
from .germselection import *
from .grammatrix import *
from .mirroring import *
from .dfe import *
from .randomcircuit import *
69 changes: 69 additions & 0 deletions pygsti/algorithms/dfe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@

import copy as _copy
import itertools as _itertools

import numpy as _np

from pygsti.algorithms import compilers as _cmpl
from pygsti.circuits import circuit as _cir
from pygsti.baseobjs import label as _lbl
from pygsti.tools import group as _rbobjs
from pygsti.tools import symplectic as _symp
from pygsti.tools import compilationtools as _comp
from pygsti.tools import internalgates as _gates
from pygsti.algorithms import randomcircuit as _rc

def sample_dfe_circuit(pspec, circuit, clifford_compilations, seed=None):
"""
... ... ... ...
"""
qubit_labels = circuit.line_labels
n = len(qubit_labels)
rand_state = _np.random.RandomState(seed) # Ok if seed is None

rand_pauli, rand_sign, pauli_circuit = _rc._sample_random_pauli(n = n, pspec = pspec, qubit_labels=qubit_labels,
absolute_compilation = clifford_compilations,
circuit = True, include_identity = False)

s_inputstate, p_inputstate, s_init_layer, p_init_layer, prep_circuit = _rc._sample_stabilizer(rand_pauli, rand_sign, clifford_compilations, qubit_labels)

s_pc, p_pc = _symp.symplectic_rep_of_clifford_circuit(pauli_circuit, pspec=pspec.subset(gate_names_to_include='all', qubit_labels_to_keep=qubit_labels)) #note: if the pspec contains gates not in pyGSTi, this

# build the initial layer of the circuit
full_circuit = prep_circuit.copy(editable=True)

# find the symplectic matrix / phase vector of the input circuit
s_rc, p_rc = _symp.symplectic_rep_of_clifford_circuit(circuit, pspec=pspec.subset(gate_names_to_include='all', qubit_labels_to_keep=qubit_labels))

s_composite, p_composite = _symp.compose_cliffords(s1 = s_init_layer, p1 = p_init_layer, s2 = s_rc, p2 = p_rc)

full_circuit.append_circuit_inplace(circuit)

s_outputstate, p_outputstate = _symp.apply_clifford_to_stabilizer_state(s_rc, p_rc, s_inputstate, p_inputstate)

# Figure out what stabilizer of s_outputstate, rand_pauli was mapped too
s_rc_inv, p_rc_inv = _symp.inverse_clifford(s_rc, p_rc) # U^(-1)
s_new_pauli, p_new_pauli = _symp.compose_cliffords(s_rc_inv, p_rc_inv, s_pc, p_pc) # PU^(-1)
s_new_pauli, p_new_pauli = _symp.compose_cliffords(s_new_pauli, p_new_pauli, s_rc, p_rc) # UPaU^(-1)

pauli_vector = p_new_pauli
pauli = [i[0] for i in _symp.find_pauli_layer(pauli_vector, [j for j in range(n)])]
measurement = ['I' if i == 'I' else 'Z' for i in pauli]

# Turn the stabilizer into an all Z and I stabilizer
s_stab, p_stab, stab_circuit = _rc._stabilizer_to_all_zs(pauli, qubit_labels, clifford_compilations)

full_circuit.append_circuit_inplace(stab_circuit)

s_inv, p_inv = _symp.inverse_clifford(s_stab, p_stab)
s_cc, p_cc = _symp.compose_cliffords(s_inv, p_inv, s_composite, p_composite)
s_cc, p_cc = _symp.compose_cliffords(s_composite, p_composite, s_stab, p_stab) # MUPaU^(-1)M^(-1)

s_outputstate, p_outputstate = _symp.apply_clifford_to_stabilizer_state(s_stab, p_stab, s_outputstate, p_outputstate)

full_circuit.done_editing()
sign = _rc._determine_sign(s_outputstate, p_outputstate, measurement)

outcircuit = full_circuit

return outcircuit, measurement, sign
1 change: 1 addition & 0 deletions pygsti/protocols/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
from .stability import *
from .vb import *
from .vbdataframe import *
from .dfe import *
74 changes: 74 additions & 0 deletions pygsti/protocols/dfe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
DFE Protocol objects
"""
#***************************************************************************************************
# Copyright 2015, 2019 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
# Under the terms of Contract DE-NA0003525 with NTESS, the U.S. Government retains certain rights
# in this software.
# Licensed 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 or in the LICENSE file in the root pyGSTi directory.
#***************************************************************************************************

from collections import defaultdict
import numpy as _np

from pygsti.protocols import protocol as _proto
from pygsti.protocols import vb as _vb
from pygsti import tools as _tools
from pygsti.algorithms import dfe as _dfe
from pygsti.protocols import rb as _rb

class DFEDesign(_vb.BenchmarkingDesign):
"""
This currently only works if `circuits` are all on the same qubits
b/c it is built on BenchmarkingDesign. Code will likely silently
break if this isn't true
"""
def __init__(self, pspec, circuits, clifford_compilations, num_samples,
descriptor='A DFE experiment', add_default_protocol=False):

circuit_lists = []
measurements = []
signs = []

# Need to add back in the seed but don't know how to correctly propagate it down
# to the sampling function
#if seed is None:
# self.seed = _np.random.randint(1, 1e6) # Pick a random seed
#else:
# self.seed = seed

for c in circuits:
dfe_circuits_for_c = []
measurements_for_c = []
signs_for_c = []
for sample_num in range(num_samples):
dfe_circ, meas, sign = _dfe.sample_dfe_circuit(pspec, c, clifford_compilations, None)
dfe_circuits_for_c.append(dfe_circ)
measurements_for_c.append(meas)
signs_for_c.append(int(sign))

circuit_lists.append(dfe_circuits_for_c)
measurements.append(measurements_for_c)
signs.append(signs_for_c)

self._init_foundation(circuit_lists, measurements, signs, num_samples, descriptor,
add_default_protocol)

def _init_foundation(self, circuit_lists, measurements, signs, num_samples, descriptor,
add_default_protocol):
# Pair these attributes with circuit data so that we serialize/truncate properly
self.paired_with_circuit_attrs = ["measurements", "signs"]

dummy_depths = list(range(len(circuit_lists)))
qubit_labels = circuit_lists[0][0].line_labels
super().__init__(dummy_depths, circuit_lists, signs, qubit_labels, remove_duplicates=False)
self.measurements = measurements
self.signs = signs
self.circuits_per_depth = num_samples
self.descriptor = descriptor

# This is a hack to do the data processing automatically
defaultfit = 'A-fixed'
self.add_default_protocol(_rb.RB(name='RB', defaultfit=defaultfit))

0 comments on commit a7da8db

Please sign in to comment.