Source code for qubiter.adv_applications.PhaseEstSEO_writer

from qubiter.SEO_writer import *
from qubiter.FouSEO_writer import *
import copy as cp


[docs]class PhaseEstSEO_writer(SEO_writer): """ The quantum phase estimation algorithm or PEA (see https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm for an introduction) was invented by Kitaev in 1995. Since then, it has been used for many purposes such as for finding the ground state energy of molecules. This class is a subclass of SEO_writer. It writes the PEA circuit that is given, for example, in the Wikipedia article just mentioned. We will divide the qubits used by PEA into 2 disjoint sets and refer to those sets as: probe qubits and atom qubits. A matrix U that acts on the atom qubits will be referred to as the atom matrix or just the atom. First a Hadamard matrix is applied to each probe qubit. Then each probe qubit interacts with a different power of the atom matrix U. Finally, an inverse quantum Fourier transform is applied to all the probe qubits together. Even though these probe-atom interactions would not change the state of the probe qubits if they were classical particles, the probes do become correlated with the atom powers and this shows up after we take the inverse Fourier transform. Note that this class writes the whole PEA circuit, but it requires as input an object of a subclass of the class AtomWriter given below. This object will write the atom matrix powers. Attributes ---------- atom_wr : AtomWriter An object of a subclass of the class AtomWriter given below. This object will write the atom matrix powers. do_perm : bool True if want quantum Fourier Transform circuit to include permutation that reverses qbit order num_probe_bits : int Number of probe qubits. """
[docs] def __init__(self, do_write, num_probe_bits, atom_writer, file_prefix, emb, do_perm=True, **kwargs): """ Constructor Parameters ---------- do_write : bool True if want constructor to write automatically without being asked. atom_writer : AtomWriter num_probe_bits : int file_prefix : str emb : CktEmbedder do_perm : bool True if want quantum Fourier Transform circuit to include permutation that reverses qbit order Returns ------- """ self.do_perm = do_perm SEO_writer.__init__(self, file_prefix, emb, **kwargs) self.num_probe_bits = num_probe_bits self.atom_wr = atom_writer self.atom_wr.english_out = self.english_out self.atom_wr.picture_out = self.picture_out self.atom_wr.ZL = self.ZL if do_write: self.write()
[docs] def write(self): """ Writes the circuit for quantum phase estimation. Returns ------- None """ num_qbits = self.emb.num_qbits_bef num_atom_bits = num_qbits - self.num_probe_bits assert num_atom_bits >= 1, "must have >=1 probe bits" # first write the Hadamards for k in range(self.num_probe_bits): self.write_one_qbit_gate(k, OneQubitGate.had2) # next write the probe controlled atoms # this pre_emb maps atom -> (atom + probes) num_qbits_bef = num_atom_bits num_qbits_aft = num_qbits bit_map = list(range(self.num_probe_bits, num_qbits)) pre_emb = CktEmbedder(num_qbits_bef, num_qbits_aft, bit_map) for k in range(self.num_probe_bits): pre_emb.extra_controls = \ Controls.new_single_trol(num_qbits, k, True) compo_emb = CktEmbedder.composition(self.emb, pre_emb) self.atom_wr.emb = compo_emb self.atom_wr.write_pow(1 << k) # finally write the inverse Fourier transform # this pre_emb maps probe bits -> (atom + probes) num_qbits_bef = self.num_probe_bits num_qbits_aft = num_qbits bit_map = list(range(num_qbits_bef)) pre_emb = CktEmbedder(num_qbits_bef, num_qbits_aft, bit_map) compo_emb = CktEmbedder.composition(self.emb, pre_emb) fou_writer = FouSEO_writer( do_write=False, file_prefix='blank', emb=compo_emb, do_perm=self.do_perm, english_out=self.english_out, picture_out=self.picture_out, ZL=self.ZL) fou_writer.write_hermitian()
[docs] def write_hermitian(self): """ Write Hermitian conjugate of circuit written by write(). Returns ------- None """ num_qbits = self.emb.num_qbits_bef num_atom_bits = num_qbits - self.num_probe_bits assert num_atom_bits >= 1, "must have >=1 probe bits" # first write the Fourier transform # this pre_emb maps probe bits -> (atom + probes) num_qbits_bef = self.num_probe_bits num_qbits_aft = num_qbits bit_map = list(range(num_qbits_bef)) pre_emb = CktEmbedder(num_qbits_bef, num_qbits_aft, bit_map) compo_emb = CktEmbedder.composition(self.emb, pre_emb) fou_writer = FouSEO_writer( do_write=False, file_prefix='blank', emb=compo_emb, do_perm=self.do_perm, english_out=self.english_out, picture_out=self.picture_out, ZL=self.ZL) fou_writer.write() # next write the probe controlled atoms # this pre_emb maps atom -> (atom + probes) num_qbits_bef = num_atom_bits num_qbits_aft = num_qbits bit_map = list(range(self.num_probe_bits, num_qbits)) pre_emb = CktEmbedder(num_qbits_bef, num_qbits_aft, bit_map) for k in reversed(range(self.num_probe_bits)): pre_emb.extra_controls = \ Controls.new_single_trol(num_qbits, k, True) compo_emb = CktEmbedder.composition(self.emb, pre_emb) self.atom_wr.emb = compo_emb self.atom_wr.write_pow_hermitian(1 << k) # finally write the Hadamards for k in reversed(range(self.num_probe_bits)): self.write_one_qbit_gate(k, OneQubitGate.had2)
[docs]class AtomWriter(SEO_writer): """ An object of this class or of a subclass thereof is an attribute of PhaseEstSEO_writer(). If test=False, this class must be subclassed. If test=True, you get an example. In this example, the atom matrix is a simple controlled Ry rotation, but more generally, it can be a whole circuit. Attributes ---------- This class has all the attributes of SEO_writer test : bool If test=True, the class uses testing parameters. If test=False, this becomes an abstract class that must be subclassed. """
[docs] def __init__(self, do_write, test=False, file_prefix=None, emb=None, **kwargs): """ Constructor Parameters ---------- do_write : bool test : bool file_prefix : str emb : CktEmbedder Returns ------- """ SEO_writer.__init__(self, file_prefix, emb, **kwargs) self.test = test if do_write: self.write()
[docs] def write_pow(self, power): """ Writes circuit for U^power, where U is the atom matrix. Parameters ---------- power : int Returns ------- None """ if not self.test: assert False num_qbits = self.emb.num_qbits_bef trols = Controls(num_qbits) tar_bit_pos = 0 for k in range(1, num_qbits): trols.set_control(k, False) trols.refresh_lists() self.write_controlled_one_qbit_gate( tar_bit_pos, trols, OneQubitGate.rot_ax, [30*power*np.pi/180, 2])
[docs] def write_pow_hermitian(self, power): """ Write Hermitian conjugate of circuit written by write_pow(). Parameters ---------- power : int Returns ------- None """ if not self.test: assert False num_qbits = self.emb.num_qbits_bef trols = Controls(num_qbits) tar_bit_pos = 0 for k in range(1, num_qbits): trols.set_control(k, False) trols.refresh_lists() self.write_controlled_one_qbit_gate( tar_bit_pos, trols, OneQubitGate.rot_ax, fun_arg_list=[-30*power*np.pi/180, 2])
[docs] def write(self): """ Same as write_pow(1) Returns ------- None """ self.write_pow(1)
[docs] def write_hermitian(self): """ Write Hermitian conjugate of circuit written by write(). Returns ------- None """ self.write_pow_hermitian(1)
if __name__ == "__main__": def main(): bit_map = list(range(7)) fin_emb = CktEmbedder(7, 8, bit_map) atom_wr = AtomWriter(do_write=False, test=True) for ZL in [True, False]: wr = PhaseEstSEO_writer(do_write=False, num_probe_bits=4, atom_writer=atom_wr, file_prefix="ph_est_test", emb=fin_emb, ZL=ZL) wr.write() wr.write_NOTA("next write h.c.") wr.write_hermitian() wr.close_files() main()