def __init__(self, file_prefix, emb, style, rad_angles=None, num_T_trols=0, num_F_trols=0, num_gbits=0, **kwargs): """ Constructor Parameters ---------- file_prefix : str emb : CktEmbedder style : str rad_angles : list(float) num_T_trols : int num_F_trols : int num_gbits : int kwargs : dict() Returns ------- None """ self.style = style self.rad_angles = rad_angles if rad_angles: self.rad_angles = ut.centered_rads1(rad_angles) self.num_T_trols = num_T_trols self.num_F_trols = num_F_trols self.num_gbits = 0 if style == 'oracular': self.num_gbits = num_gbits num_bits = emb.num_bits_bef assert num_bits >= 2, "multiplexor must have at least 2 qubits" ntf = num_T_trols + num_F_trols num_MP_trols = num_bits - ntf - num_gbits - 1 assert num_MP_trols > 0 if rad_angles: assert len(rad_angles) == (1 << num_MP_trols), \ "wrong number of multiplexor angles" SEO_writer.__init__(self, file_prefix, emb, **kwargs)
def write_exact(self): """ Writes in English file a multiple line, exact representation of the d-unitary. Returns ------- None """ num_bits = self.emb.num_bits_bef nt = self.num_T_trols nf = self.num_F_trols ntf = nt + nf num_MP_trols = num_bits - ntf - self.num_gbits rads_arr = np.array(ut.centered_rads1(self.rad_angles)) if np.linalg.norm(rads_arr) < 1e-6: print("unit d-unitary") return conj_rads = HadamardTransform.ht(num_MP_trols, rads_arr) num_factors = (1 << num_MP_trols) f, lazy = BitVector.lazy_advance(0, 0) # start at f=1 cur_rot_bpos = 0 prev_rot_bpos = 0 cur_bvec = BitVector(num_MP_trols+1, 1) # start at 1 prev_bvec = BitVector(num_MP_trols+1, 0) diff_bvec = BitVector(num_MP_trols+1, 0) TF_dict = dict(enumerate([True]*nt + [False]*nf)) trols1 = Controls(num_bits) trols1.bit_pos_to_kind = TF_dict.copy() trols1.refresh_lists() trols2 = Controls(num_bits) def write_cnots(diff_bvec1, init_prev_T_bit): prev_T_bit = init_prev_T_bit while True: cur_T_bit = diff_bvec1.find_T_bit_to_left_of(prev_T_bit) if cur_T_bit == -1: break trols2.bit_pos_to_kind = TF_dict.copy() trols2.bit_pos_to_kind[cur_T_bit + ntf] = True trols2.refresh_lists() self.write_controlled_one_bit_gate( ntf + init_prev_T_bit, trols2, OneBitGates.sigx) prev_T_bit = cur_T_bit norma = np.power(np.sqrt(2), num_MP_trols) # for first A factor, f = 0, just global phase # write conditioned global phase global_ph = conj_rads[0]*norma/len(conj_rads) if abs(global_ph) > 1e-6: self.write_controlled_one_bit_gate(ntf, trols1, OneBitGates.phase_fac, [global_ph]) while f < num_factors: cur_bvec.dec_rep = lazy # Since we have excluded f=0, f always has at least one T bit. cur_rot_bpos = cur_bvec.find_rightmost_T_bit() # print(cur_bvec.get_bit_string(), cur_rot_bpos) rads = ut.centered_rads(conj_rads[cur_bvec.dec_rep]/norma) if abs(rads) < 1e-6: pass else: # If cur_rot_bpos equals (doesn't equal) prev_rot_bpos, # then there is (isn't) cancellation between: # (1)the c-nots sigma_x(cur_rot_bpos)^n() # contributed by the right part of the current A factor # and # (2)the c-nots sigma_x(prev_rot_bpos)^n() # contributed by the left part of the previous A factor. if cur_rot_bpos == prev_rot_bpos: diff_bvec = BitVector.new_with_T_on_diff( cur_bvec, prev_bvec) write_cnots(diff_bvec, cur_rot_bpos) else: write_cnots(prev_bvec, prev_rot_bpos) write_cnots(cur_bvec, cur_rot_bpos) diff_bvec = BitVector.copy(cur_bvec) self.write_controlled_one_bit_gate( ntf + cur_rot_bpos, trols1, OneBitGates.rot_ax, [rads, 3]) prev_bvec = BitVector.copy(cur_bvec) prev_rot_bpos = cur_rot_bpos f, lazy = BitVector.lazy_advance(f, lazy) # Don't forget the leftmost c-nots write_cnots(prev_bvec, prev_rot_bpos)
def write_exact(self): """ Writes in English file a multiple line, exact representation of the multiplexor. Returns ------- None """ num_bits = self.emb.num_bits_bef nt = self.num_T_trols nf = self.num_F_trols ntf = nt + nf num_MP_trols = num_bits - ntf - self.num_gbits - 1 rads_arr = np.array(ut.centered_rads1(self.rad_angles)) if np.linalg.norm(rads_arr) < 1e-6: print("unit multiplexor") return conj_rads = HadamardTransform.ht(num_MP_trols, rads_arr) num_factors = (1 << num_MP_trols) cur_bvec = BitVector(num_MP_trols+1, 0) # start at zero prev_bvec = BitVector(num_MP_trols+1, 0) TF_dict = dict(enumerate([True]*nt + [False]*nf)) trols1 = Controls(num_bits) trols1.bit_pos_to_kind = TF_dict.copy() trols1.refresh_lists() trols2 = Controls(num_bits) def write_cnots(diff_bvec): prev_T_bit = num_MP_trols while True: cur_T_bit = diff_bvec.find_T_bit_to_right_of(prev_T_bit) if cur_T_bit == -1: break trols2.bit_pos_to_kind = TF_dict.copy() trols2.bit_pos_to_kind[cur_T_bit + ntf] = True trols2.refresh_lists() self.write_controlled_one_bit_gate( ntf + num_MP_trols, trols2, OneBitGates.sigx) prev_T_bit = cur_T_bit norma = np.power(np.sqrt(2), num_MP_trols) f = 0 lazy = 0 while f < num_factors: rads = conj_rads[cur_bvec.dec_rep]/norma if abs(rads) < 1e-6: pass else: diff_bvec = BitVector.new_with_T_on_diff(cur_bvec, prev_bvec) write_cnots(diff_bvec) self.write_controlled_one_bit_gate( ntf + num_MP_trols, trols1, OneBitGates.rot_ax, [rads, 2]) prev_bvec = BitVector.copy(cur_bvec) f, lazy = BitVector.lazy_advance(f, lazy) cur_bvec.dec_rep = lazy # Don't forget the leftmost c-nots: diff_bvec = prev_bvec write_cnots(diff_bvec)