Source code for blind_transpiler.controllers.ubqc
from ..essentials.bqc_instruction import BQCInstruction
from ..essentials.bop import BOP
from .base import BaseController
from ..global_value_store import GlobalVariablesAndFunctions
[docs]
class UBQC(BaseController):
def __init__(self):
BaseController.__init__(self)
None
[docs]
def ubqc(self, trans_circ, keys):
'''
Convert the circuit in full-blind quantum computation circuit.
Logic:
iterate the circuit element by element
check if element is client implementable
add instruction as op_type = 'client'
if not
used UBQC class to convert get the sequence of gates and store in list with order no.
Args:
trans_circ (QuantumCircuit):
transpiled circuit in the basis set whose translation is present in translator library.
Returns:
bqc_instruction (list[BOP])
list of BOP in order which they need to be implemented.
'''
GVF = GlobalVariablesAndFunctions()
from ..translators.universalRecursiveRotationTranslator import UniversalRecursiveRotationTranslator
# client_basis = self.client_basis
# server_basis = self.ubqc_server_basis
constant_compute_space = GVF.ubqc_compute_space # defined it at a central location
bqc_instructions = BQCInstruction() # is list of tuples (step, Op)
bqc_instructions.n_qubits = trans_circ.num_qubits + constant_compute_space # add extra qubits for server resource set
bqc_instructions.n_cbits = trans_circ.count_ops().get('measure', 0)
bqc_instructions.format = 'ubqc'
translation_map = self._create_translation_map(UniversalRecursiveRotationTranslator(), format='ubqc')
key_counter = 0
for step, data in enumerate(trans_circ.data):
instr = data.operation
qargs = data.qubits
cargs = data.clbits
qargs = tuple([trans_circ.find_bit(q)[0] + constant_compute_space for q in qargs]) # extract index of qubit from QuantumRegister element
# and update the qargs to adjust the server resource set padding
cargs = tuple([trans_circ.find_bit(c)[0] for c in cargs]) # as measure will not happen on resource set, no need to add the space
if instr.name in self.client_basis:
gate = instr.__class__(*instr.params) # takes out the name of class from the instr class
if instr.name == 'measure':
secure_gate = BOP('measure', qargs, cargs, gate, gate_seq = step )
else:
secure_gate = BOP('client', qargs, cargs, gate, gate_seq = step )
bqc_instructions.add_elements(secure_gate)
elif instr.name in self.server_basis:
translation_func = translation_map[instr.name]
gate_key_size = self.ubqc_key_map[instr.name]
if instr.name == 'rz': # as 'rz' gate take parameter theta
# print(f'instr rz {instr.params[0]}')
secure_gate = translation_func(instr.params[0], tuple(keys[key_counter: key_counter+gate_key_size]), qargs, gate_seq= step)
else:
secure_gate = translation_func(tuple(keys[key_counter: key_counter+gate_key_size]), qargs, gate_seq= step)
bqc_instructions.add_elements( [*secure_gate] )
key_counter += gate_key_size
elif instr.name in ['barrier']: #barrier does not effect only visual indication, update rules outside to include it in transpiled circuit
from qiskit.circuit.library import Barrier
secure_gate = BOP('barrier', qargs , cargs , Barrier(len(qargs)), gate_seq = step )
continue
elif instr.name in ['barrier']: # no need to do anything if gate is barrier
continue
else:
raise KeyError(f'Gate {instr.name} not in any basis set.')
return bqc_instructions