Source code for blind_transpiler.controllers.qhe
from ..essentials.bqc_instruction import BQCInstruction
from ..essentials.bop import BOP
from ..translators.homomorphicTranslator import HomomorphicTranslation
from .base import BaseController
from ..global_value_store import GlobalVariablesAndFunctions
# class HDQC(BaseController):
[docs]
class QHE(BaseController):
def __init__(self):
BaseController.__init__(self)
None
[docs]
def qhe(self, trans_circ, keys):
'''
Convert the circuit in half-blind quantum computation circuit.
Note: An efficient way to coding might be through converting to DAG and adding the circuit, for now do the easy one.
Logic:
iterate the circuit element by element
check if element is client implementable
add instruction as op_type = 'client'
if not
used 'HomomorphicTranslation' 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()
constant_compute_space = GVF.qhe_compute_space
translation_map = self._create_translation_map(HomomorphicTranslation(), format='qhe')
bqc_instructions = BQCInstruction() # is list of tuples (step, Op)
bqc_instructions.n_qubits = trans_circ.num_qubits + constant_compute_space # one ancilla qubit for recursive decryption of rz
bqc_instructions.n_cbits = trans_circ.count_ops().get('measure', 0)
bqc_instructions.format = 'qhe'
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
cargs = tuple([trans_circ.find_bit(c)[0] for c in cargs]) # extract index of qubit from ClassicalRegister element
if instr.name in self.client_basis:
gate = instr.__class__(*instr.params)
if instr.name == 'measure':
secure_gate = BOP('measure', qargs, cargs, gate, gate_seq = step )
#### NOTE
# Throughing an error if you give QC(x,x) and then apply measure_all() on it.
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.qhe_key_map[instr.name]
if instr.name == 'rz': # as 'rz' gate take parameter theta
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
else:
raise KeyError(f'Gate {instr.name} not in any basis set.')
return bqc_instructions