def create_grover(oracle_type, oracle_method):
    # Build the circuit
    if oracle_method=="log":
        algorithm = Grover(LogicalExpressionOracle(oracle_type),num_iterations=num_iterations)
        oracle_circuit = Grover(LogicalExpressionOracle(oracle_type)).construct_circuit()
    else:
        algorithm = Grover(TruthTableOracle(oracle_type),num_iterations=num_iterations)
        oracle_circuit = Grover(TruthTableOracle(oracle_type)).construct_circuit()

    display(oracle_circuit.draw(output="mpl"))
    display(algorithm)
    return(algorithm)
Beispiel #2
0
class byskit():
    def __init__(self, backend, parents, child, evd=None):
        self.backend = backend
        self.parents = parents
        self.child = child
        self.n = int(np.shape(parents)[0] / 2)
        self.n_child = np.shape(child)[1]
        self.ctrl = QuantumRegister(self.n, 'ctrl')
        self.anc = QuantumRegister(self.n - 1, 'anc')
        self.tgt = QuantumRegister(self.n_child, 'tgt')
        if evd != None:
            self.oracle = QuantumRegister(evd, 'oracle')
            self.circ = QuantumCircuit(self.ctrl, self.anc, self.tgt,
                                       self.oracle)
        else:
            self.circ = QuantumCircuit(self.ctrl, self.anc, self.tgt)

        #self.c_ctrl = ClassicalRegister(self.n, 'c_ctrl')
        #self.c_tgt = ClassicalRegister(self.n_child, 'c_tgt')

        self.parent_init()
        self.child_init()

    def parent_init(self):
        for i in range(self.n):
            theta = self.calc_theta(self.parents[2 * i],
                                    self.parents[2 * i + 1])
            self.circ.ry(theta, i)

        self.circ.barrier()

    def child_init(self):
        self.a = np.arange(0, 2**self.n)
        self.gates = []
        for i in self.a:
            s = str(np.binary_repr(i, width=self.n))
            self.gates.append(s)

        for i in range(2**self.n):
            self.xgate(self.gates[i])
            for j in range(self.n_child):
                theta = self.calc_theta(self.child[2 * i + 1, j],
                                        self.child[2 * i, j])
                self.cn_ry(theta, j)
            self.xgate(self.gates[i])
            self.circ.barrier()

    def xgate(self, gate):
        for index, item in enumerate(gate):
            if int(item) == 0:
                self.circ.x(index)

    #RY gates
    def cn_ry(self, theta, target):
        # compute
        self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])
        for i in range(2, self.n):
            self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])

        # copy
        self.circ.cry(theta, self.anc[self.n - 2], self.tgt[target])

        # uncompute
        for i in range(self.n - 1, 1, -1):
            self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])
        self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])

    def calc_theta(self, p1, p0):
        return 2 * np.arctan(np.sqrt((p1) / (p0)))

    def plot(self):
        self.circ.draw(output='mpl')
        plt.show()

    def execute_circ(self):
        self.circ.measure_all()
        results = execute(self.circ, self.backend, shots=4321)
        return results

    def rejection_sampling(self,
                           evidence,
                           shots=1000,
                           amplitude_amplification=False):
        # Run job many times to get multiple samples
        samples_list = []
        self.n_samples = shots

        if amplitude_amplification == True:
            self.amplitude_amplification(evidence)

        self.circ.measure_all()

        #self.circ.measure((self.ctrl, self.tgt),(self.c_ctrl, self.c_tgt))

        for i in range(self.n_samples):
            job = execute(self.circ, backend=self.backend, shots=1)
            result = list(job.result().get_counts(self.circ).keys())[0]
            accept = True
            for e in evidence:
                if result[evidence[e]['n']] == evidence[e]['state']:
                    pass
                else:
                    accept = False
            if accept == True:
                #print('Accepted result ', result)
                samples_list.append(result)

        print()
        print(self.n_samples, 'samples drawn:', len(samples_list),
              'samples accepted,', self.n_samples - len(samples_list),
              'samples rejected.')
        print('Percentage of samples rejected: ',
              100 * (1 - (len(samples_list) / self.n_samples)), '%')

        return samples_list

    def evaluate(self, samples_list, observations):
        p_o = 0
        for sample in samples_list:
            accept = True
            for o in observations:
                if sample[observations[o]['n']] == observations[o]['state']:
                    pass
                else:
                    accept = False
            if accept == True:
                #print('Observation true given evidence')
                p_o += 1
        p_o /= len(samples_list)

        print('Probabilty of observations given evidence = ', p_o)

        return p_o

    def amplitude_amplification(self, evidence):
        self.state_preparation = self.circ
        self.oracle = QuantumCircuit(self.ctrl, self.anc, self.tgt)
        for index, e in enumerate(evidence):
            if evidence[e]['state'] == '1':
                self.oracle.z([evidence[e]['n']])

        self.grover_op = Grover(self.oracle,
                                state_preparation=self.state_preparation)
        self.grover_op.draw()

    def oracle(self):
        pass

    def u_gate(self):
        pass
Beispiel #3
0
class byskit():
    def __init__(self, backend, network, loaded_net, evd=None):
        self.backend = backend
        self.network = network
        self.net_keys = [key for key in self.network]
        self.loaded_net = loaded_net
        self.reg = {}

        self.create_circ()

        self.root_init()

        child_index = np.array([0, 0])
        parent_index = np.array([0, 0])
        for index in range(len(self.net_keys) - 1):
            parent_key = self.net_keys[index]
            child_key = self.net_keys[index + 1]
            if parent_key != 'root':
                parent_index = np.array([
                    parent_index[1],
                    parent_index[1] + self.network[self.net_keys[index + 1]]
                ])
            child_index = np.array([
                child_index[1],
                child_index[1] + self.network[self.net_keys[index + 1]]
            ])
            self.child_init(parent_key, parent_index, child_key, child_index)

    def create_circ(self):
        self.n_anc = 0
        self.n_tgt = 0
        for key in self.network:
            if key == 'root':
                n = self.network['root']
                self.reg['cntrl'] = QuantumRegister(self.network['root'],
                                                    'cntrl')

            else:
                self.n_anc = max(n - 1, self.n_anc)
                self.n_tgt += self.network[key]
                n = self.network[key]
        self.reg['anc'] = QuantumRegister(self.n_anc, 'anc')
        self.reg['tgt'] = QuantumRegister(self.n_tgt, 'tgt')

        self.circ = QuantumCircuit(self.reg['cntrl'], self.reg['anc'],
                                   self.reg['tgt'])

    def root_init(self):
        for i in range(self.network['root']):
            theta = self.calc_theta(self.loaded_net['root'][2 * i],
                                    self.loaded_net['root'][2 * i + 1])
            self.circ.ry(theta, i)

        self.circ.barrier()

    def child_init(self, parent_key, parent_index, child_key, child_index):
        parent_index = parent_index[0]
        child_index = child_index[0]
        self.a = np.arange(0, 2**self.network[parent_key])
        self.gates = []
        for i in self.a:
            s = str(np.binary_repr(i, width=self.network[parent_key]))
            self.gates.append(s)

        for i in range(2**self.network[parent_key]):
            self.xgate(self.gates[i], parent_index)
            for j in range(self.network[child_key]):
                theta = self.calc_theta(
                    self.loaded_net[child_key][2 * i + 1, j],
                    self.loaded_net[child_key][2 * i, j])
                self.cn_ry(theta, j, parent_key, parent_index, child_key,
                           child_index)
            self.xgate(self.gates[i], parent_index)
            self.circ.barrier()

    def xgate(self, gate, parent_index):
        for index, item in enumerate(gate):
            if int(item) == 0:
                self.circ.x(index + parent_index)

    #RY gates
    def cn_ry(self, theta, target, parent_key, parent_index, child_key,
              child_index):
        # compute
        if parent_key == 'root':
            self.circ.ccx(self.reg['cntrl'][0], self.reg['cntrl'][1],
                          self.reg['anc'][0])
            for i in range(2, self.network[parent_key]):
                self.circ.ccx(self.reg['cntrl'][i], self.reg['anc'][i - 2],
                              self.reg['anc'][i - 1])

            # copy
            self.circ.cry(theta, self.reg['anc'][self.network[parent_key] - 2],
                          self.reg['tgt'][target])

            # uncompute
            for i in range(self.network[parent_key] - 1, 1, -1):
                self.circ.ccx(self.reg['cntrl'][i], self.reg['anc'][i - 2],
                              self.reg['anc'][i - 1])
            self.circ.ccx(self.reg['cntrl'][0], self.reg['cntrl'][1],
                          self.reg['anc'][0])

        else:
            self.circ.ccx(self.reg['tgt'][parent_index + 0],
                          self.reg['tgt'][parent_index + 1],
                          self.reg['anc'][0])
            for i in range(2, self.network[parent_key]):
                self.circ.ccx(self.reg['tgt'][parent_index + i],
                              self.reg['anc'][i - 2], self.reg['anc'][i - 1])

            # copy
            self.circ.cry(theta, self.reg['anc'][self.network[parent_key] - 2],
                          self.reg['tgt'][child_index + target])

            # uncompute
            for i in range(self.network[parent_key] - 1, 1, -1):
                self.circ.ccx(self.reg['tgt'][parent_index + i],
                              self.reg['anc'][i - 2], self.reg['anc'][i - 1])
            self.circ.ccx(self.reg['tgt'][parent_index + 0],
                          self.reg['tgt'][parent_index + 1],
                          self.reg['anc'][0])

    def calc_theta(self, p1, p0):
        return 2 * np.arctan(np.sqrt((p1) / (p0)))

    def plot(self):
        self.circ.draw(output='mpl')
        plt.show()

    def execute_circ(self):
        self.circ.measure_all()
        results = execute(self.circ, self.backend, shots=4321)
        return results

    def rejection_sampling(self,
                           evidence,
                           shots=5000,
                           amplitude_amplification=False):
        # Run job many times to get multiple samples
        samples_list = []
        self.n_samples = shots

        if amplitude_amplification == True:
            self.amplitude_amplification(evidence)

        self.circ.measure_all()

        for i in range(self.n_samples):
            job = execute(self.circ, backend=self.backend, shots=1)
            result = list(job.result().get_counts(self.circ).keys())[0]
            accept = True
            for e in evidence:
                if result[evidence[e]['n']] == evidence[e]['state']:
                    pass
                else:
                    accept = False
            if accept == True:
                #print('Accepted result ', result)
                samples_list.append(result)

        print()
        print(self.n_samples, 'samples drawn:', len(samples_list),
              'samples accepted,', self.n_samples - len(samples_list),
              'samples rejected.')
        print('Percentage of samples rejected: ',
              100 * (1 - (len(samples_list) / self.n_samples)), '%')

        return samples_list

    def evaluate(self, samples_list, observations):
        p_o = 0
        for sample in samples_list:
            accept = True
            for o in observations:
                if sample[observations[o]['n']] == observations[o]['state']:
                    pass
                else:
                    accept = False
            if accept == True:
                #print('Observation true given evidence')
                p_o += 1
        p_o /= len(samples_list)

        print('Probabilty of observations given evidence = ', p_o)

        return p_o

    def amplitude_amplification(self, evidence):
        self.state_preparation = self.circ
        self.oracle = QuantumCircuit(self.ctrl, self.anc, self.tgt)
        for index, e in enumerate(evidence):
            if evidence[e]['state'] == '1':
                self.oracle.z([evidence[e]['n']])

        self.grover_op = Grover(self.oracle,
                                state_preparation=self.state_preparation)
        self.grover_op.draw()

    def oracle(self):
        pass

    def u_gate(self):
        pass