├── .idea
├── .gitignore
├── Byskit.iml
├── inspectionProfiles
│ └── profiles_settings.xml
├── misc.xml
├── modules.xml
├── other.xml
└── vcs.xml
├── .ipynb_checkpoints
├── Bayes_net-checkpoint.ipynb
├── Test notebook-checkpoint.ipynb
├── many_to_many-checkpoint.ipynb
└── test-checkpoint.ipynb
├── Bayes_net.ipynb
├── Example-byskit.py
├── README.md
├── README.txt
├── Test notebook.ipynb
├── archive
├── CnRy.py
├── byskit-old.py
├── datastructure.py
├── fig5.py
└── many_to_many.ipynb
├── byskit-two-layer.py
├── byskit.py
├── presentation.pdf
└── test.ipynb
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/Byskit.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/other.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.ipynb_checkpoints/Bayes_net-checkpoint.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [],
3 | "metadata": {},
4 | "nbformat": 4,
5 | "nbformat_minor": 4
6 | }
7 |
--------------------------------------------------------------------------------
/.ipynb_checkpoints/test-checkpoint.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [],
3 | "metadata": {},
4 | "nbformat": 4,
5 | "nbformat_minor": 4
6 | }
7 |
--------------------------------------------------------------------------------
/Bayes_net.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "https://medium.com/analytics-vidhya/quantum-machine-learning-inference-on-bayesian-networks-351f242816e8"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "name": "stderr",
17 | "output_type": "stream",
18 | "text": [
19 | "/home/sebastian/anaconda/envs/Quiskit/lib/python3.8/site-packages/qiskit/providers/ibmq/ibmqfactory.py:192: UserWarning: Timestamps in IBMQ backend properties, jobs, and job results are all now in local time instead of UTC.\n",
20 | " warnings.warn('Timestamps in IBMQ backend properties, jobs, and job results '\n"
21 | ]
22 | }
23 | ],
24 | "source": [
25 | "from qiskit.tools.jupyter import *\n",
26 | "from qiskit import IBMQ\n",
27 | "IBMQ.load_account()\n",
28 | "#provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')\n",
29 | "provider = IBMQ.get_provider(hub='ibm-q-oxford', group='on-boarding', project='on-boarding-proj') \n",
30 | "\n",
31 | "from qiskit import QuantumRegister, ClassicalRegister \n",
32 | "from qiskit import QuantumCircuit, Aer\n",
33 | "from qiskit import execute\n",
34 | "\n",
35 | "# Create one 4 qubit QuantumRegister to hold the Bayesian network and an ancilla qubit,\n",
36 | "# and a 3 bit ClassicalRegister to hold the sampled values\n",
37 | "net = QuantumRegister(4, 'qreg')\n",
38 | "cl = ClassicalRegister(3, 'creg')\n",
39 | "\n",
40 | "circ = QuantumCircuit(net, cl, name='circ')\n"
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 6,
46 | "metadata": {},
47 | "outputs": [],
48 | "source": [
49 | "from numpy import arcsin, sqrt, pi\n",
50 | "\n",
51 | "def probToAngle(prob):\n",
52 | " \"\"\"\n",
53 | " Converts a given P(1) value into an equivalent theta value.\n",
54 | " \"\"\"\n",
55 | " return 2*arcsin(sqrt(prob))"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": 3,
61 | "metadata": {},
62 | "outputs": [
63 | {
64 | "data": {
65 | "text/plain": [
66 | ""
67 | ]
68 | },
69 | "execution_count": 3,
70 | "metadata": {},
71 | "output_type": "execute_result"
72 | }
73 | ],
74 | "source": [
75 | "# Setting up a qubit to represent the variable P\n",
76 | "circ.u3(probToAngle(0.35), 0, 0, net[0])\n",
77 | "\n",
78 | "# Since we have P = 1, we use the second row of the probability table for the variable E\n",
79 | "circ.u3(probToAngle(0.76), 0, 0, net[1])\n",
80 | "\n",
81 | "# Setting up the qubit representing H assuming that E = 0\n",
82 | "circ.u3(probToAngle(0.39), 0, 0, net[2])"
83 | ]
84 | },
85 | {
86 | "cell_type": "code",
87 | "execution_count": 4,
88 | "metadata": {},
89 | "outputs": [],
90 | "source": [
91 | "def oracle(circ):\n",
92 | " \"\"\"\n",
93 | " Implements an oracle that flips the sign of states that contain P = 1.\n",
94 | " \"\"\"\n",
95 | " circ.cu3(pi, pi, 0, net[0], net[1])\n",
96 | " circ.cu3(pi, pi, 0, net[0], net[1]) \n",
97 | " return circ\n",
98 | "\n",
99 | "\n",
100 | "def u_gate(circ):\n",
101 | " \"\"\"\n",
102 | " Implements the U gate that flips states about the average amplitude.\n",
103 | " \"\"\"\n",
104 | " # Implements the quantum circuit that converts ψ -> |000...0>\n",
105 | " circ.u3(-1*probToAngle(0.35), 0, 0, net[0])\n",
106 | " circ.u3(-1*probToAngle(0.76), 0, 0, net[1])\n",
107 | " circ.u3(-1*probToAngle(0.39), 0, 0, net[2])\n",
108 | "\n",
109 | " # Flipping the |000...0> state using a triple controlled Z gate condtioned on P, E and H, \n",
110 | " # and applied to the ancilla\n",
111 | " circ.x(net)\n",
112 | " circ.cu1(pi/4, net[0], net[3])\n",
113 | " circ.cx(net[0], net[1])\n",
114 | " circ.cu1(-pi/4, net[1], net[3])\n",
115 | " circ.cx(net[0], net[1])\n",
116 | " circ.cu1(pi/4, net[1], net[3])\n",
117 | " circ.cx(net[1], net[2])\n",
118 | " circ.cu1(-pi/4, net[2], net[3])\n",
119 | " circ.cx(net[0], net[2])\n",
120 | " circ.cu1(pi/4, net[2], net[3])\n",
121 | " circ.cx(net[1], net[2])\n",
122 | " circ.cu1(-pi/4, net[2], net[3])\n",
123 | " circ.cx(net[0], net[2])\n",
124 | " circ.cu1(pi/4, net[2], net[3])\n",
125 | " circ.x(net)\n",
126 | "\n",
127 | " # Implements the quantum circuit that converts |000...0> -> ψ \n",
128 | " circ.u3(probToAngle(0.35), 0, 0, net[0])\n",
129 | " circ.u3(probToAngle(0.76), 0, 0, net[1])\n",
130 | " circ.u3(probToAngle(0.39), 0, 0, net[2])\n",
131 | "\n",
132 | " return circ"
133 | ]
134 | },
135 | {
136 | "cell_type": "code",
137 | "execution_count": 7,
138 | "metadata": {},
139 | "outputs": [
140 | {
141 | "data": {
142 | "text/plain": [
143 | ""
144 | ]
145 | },
146 | "execution_count": 7,
147 | "metadata": {},
148 | "output_type": "execute_result"
149 | }
150 | ],
151 | "source": [
152 | "# Apply oracle and U gate twice\n",
153 | "circ = oracle(circ)\n",
154 | "circ = u_gate(circ)\n",
155 | "circ = oracle(circ)\n",
156 | "circ = u_gate(circ)\n",
157 | "circ.x(net[0])\n",
158 | "\n",
159 | "# Measure E, and rotate H to the P(1) value in the second row of the P(H|E) table condtioned on E\n",
160 | "circ.measure(net[1], cl[1])\n",
161 | "circ.u3(probToAngle(0.82) - probToAngle(0.39), 0, 0, net[2])\n",
162 | "\n",
163 | "# Sample by measuring the rest of the qubits\n",
164 | "circ.measure(net[0], cl[0])\n",
165 | "circ.measure(net[2], cl[2])"
166 | ]
167 | },
168 | {
169 | "cell_type": "code",
170 | "execution_count": 10,
171 | "metadata": {},
172 | "outputs": [
173 | {
174 | "name": "stdout",
175 | "output_type": "stream",
176 | "text": [
177 | "\n",
178 | "1000 samples drawn: 656 samples accepted, 344 samples rejected.\n",
179 | "Percentage of samples rejected: 34.4 %\n",
180 | "P(H = 0| P = 1) = 0.1722560975609756\n",
181 | "\n"
182 | ]
183 | }
184 | ],
185 | "source": [
186 | "# Get backend from Aer provider\n",
187 | "backend = Aer.get_backend('qasm_simulator')\n",
188 | "\n",
189 | "# Run job many times to get multiple samples\n",
190 | "samples_list = []\n",
191 | "n_samples = 1000\n",
192 | "\n",
193 | "for i in range(n_samples):\n",
194 | " job = execute(circ, backend=backend, shots=1)\n",
195 | " result = list(job.result().get_counts(circ).keys())[0]\n",
196 | " if result[2] == '1':\n",
197 | " samples_list.append(result)\n",
198 | "\n",
199 | "# Printing the number of useful samples and percentage of samples rejected\n",
200 | "print()\n",
201 | "print(n_samples, 'samples drawn:', len(samples_list), 'samples accepted,', n_samples-len(samples_list), 'samples rejected.' )\n",
202 | "print('Percentage of samples rejected: ', 100*(1 - (len(samples_list)/n_samples)), '%')\n",
203 | "\n",
204 | "# Computing P(H = 0| P = 1)\n",
205 | "p_H = 0\n",
206 | "\n",
207 | "for i in samples_list:\n",
208 | " if i[0] == '0':\n",
209 | " p_H += 1\n",
210 | "\n",
211 | "p_H /= len(samples_list)\n",
212 | "\n",
213 | "print('P(H = 0| P = 1) =', p_H)\n",
214 | "print()"
215 | ]
216 | },
217 | {
218 | "cell_type": "markdown",
219 | "metadata": {},
220 | "source": []
221 | },
222 | {
223 | "cell_type": "code",
224 | "execution_count": null,
225 | "metadata": {},
226 | "outputs": [],
227 | "source": []
228 | }
229 | ],
230 | "metadata": {
231 | "kernelspec": {
232 | "display_name": "Python 3",
233 | "language": "python",
234 | "name": "python3"
235 | },
236 | "language_info": {
237 | "codemirror_mode": {
238 | "name": "ipython",
239 | "version": 3
240 | },
241 | "file_extension": ".py",
242 | "mimetype": "text/x-python",
243 | "name": "python",
244 | "nbconvert_exporter": "python",
245 | "pygments_lexer": "ipython3",
246 | "version": "3.8.5"
247 | }
248 | },
249 | "nbformat": 4,
250 | "nbformat_minor": 4
251 | }
252 |
--------------------------------------------------------------------------------
/Example-byskit.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mlvqc/Byskit/bddf9834e29fea0f19b39a2e331201d17aabc6f1/Example-byskit.py
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Byskit
2 |
3 | A compiler for automatically turning simple classical Bayesian networks into quantum circuits to run on Qiskit.
4 |
5 | Development team: [Sebastian Orbell](https://www.linkedin.com/in/sebastian-orbell-57541b193/), [Joseph Hickie](https://www.linkedin.com/in/joseph-hickie/) and [Brandon Severin](https://brandonseverin.carrd.co/) from the [Natalia Ares Group](https://www.natalia-ares.com/) at the University of Oxford.
6 |
7 | Requirements: [Anaconda Python](https://www.anaconda.com/products/individual), [Qiskit](https://qiskit.org/)
8 |
9 | See more: https://sebastianorbell.github.io/byskit.html
10 |
11 | ## Summary
12 |
13 | > "Would you risk it for a quantum biscuit?"
14 |
15 | Byskit plants an initial step towards taking full advantage of the amplitude amplification when running discrete Bayesian networks on a quantum computer. It provides the ability to easily translate a simple classical discrete Bayesian network to its corresponding quantum circuit. Previously these circuits were drawn manually. By ‘simple’ we mean the network has two generations i.e. one set of parents and one set of children. Future iterations could configure quantum circuits for arbitrarily complex Bayesian networks.
16 |
17 | To have a play download the code and checkout the "Test notebook.ipynb" Jupyter Notebook.
18 |
19 | ## Background
20 |
21 | To quickly get everyone up to speed we will first explain what a Bayesian network is.
22 |
23 | ### Classical Bayesian Networks
24 |
25 | A Bayesian network is a probabilistic model that graphically represents random variables and the conditional dependencies between them. The model is based on a directed acyclic graph with nodes representing random variables and the directed edges between them representing their conditional dependencies. These dependencies are modelled with conditional probability distributions or tables.
26 |
27 | These probability distributions can either be specified manually or learned using data. Once they are populated, we can use the network to make inferences of different types. For instance, we can make predictions about outcomes based on a set of inputs, or we can make diagnoses where we infer what inputs may have led to an observed outcome. These inferences can be exact or approximate.
28 |
29 | The main graph in this slide is simple, with a child and two roots. However, Bayesian networks can be arbitrarily complex - see the example to the right. Performing exact inference on bayesian networks is sharp-P hard, meaning they become classically intractable as they grow very large. We can use approximate inference to avoid this, but this is still NP hard generally. Approximate inference uses other techniques such as Markov Chain Monte Carlo sampling or rejection sampling methods to speed up inference.
30 |
31 | ### Quantum Implementation
32 |
33 | By implementing a bayesian network on quantum hardware, it is possible to obtain a square root speedup of rejection sampling of a Bayesian network. This is based on the principle of amplitude amplification, which is the generalisation of Grover’s algorithm, to facilitate a quantum version of rejection sampling. Quantum rejection sampling has been implemented and demonstrated on toy problems such as stock price prediction and bankruptcy protection.
34 |
35 | The probability of each node’s outcome is mapped to a probability amplitude in a qubit by preparing each one in a specified state. Where in the graph representation we would propagate the probabilities through each layer, in the quantum hardware implementation we use qubit gates to change the states of control qubits and subsequently read out the measurement qubit to take a sample.
36 |
37 | ## Algorithm Workflow
38 |
39 | First we start out with the drawing of the classical network. Then to generate the quantum implementation of the network Byskit:
40 |
41 | 1. Maps each node to a qubit (this one to one mapping is easy if each node has only two states).
42 | 2. Maps the marginal/ conditional probabilities of each node to the probability amplitudes associated with qubit states.
43 | 3. Composes $$C^{n}R_{Y}\theta$$ rotation gates, using ancilla qubits, to achieve the required probability amplitudes.
44 |
45 | ## Use Cases
46 |
47 | We keep the use cases of any Bayesian network but obtain the benefit of the heft of the quantum system. This enables us to run Bayesian networks with large numbers of nodes and take advantage of the computational speed up provided by quantum computers. Here we have highlighted some typical issues that may fall into this category. Computational drug design, a specific example would be looking at the probabilities of particular protein mutations in antibodies not being rejected and attacked by the human immune system while also being effective at binding with the target pathogen. Diagnostics and decision automation, this could be biological or physical when the feature sets are large.
48 |
49 | ## Looking Forward
50 |
51 | Byskit is at the moment a simple implementation. Bayesian networks can be much more complex in the number of parents and children in addition to how the generations link with each other. Before we can go and tackle the world’s hardest problems we will still need to add the functionality of being able to compile more complex Bayesian networks. We will then interface Byskit with popular Bayesian network libraries such as tensorflow-probability.
52 |
53 |
--------------------------------------------------------------------------------
/README.txt:
--------------------------------------------------------------------------------
1 | Would you risk it for quantum Byskit?
2 |
3 | A Bayesian compiler for Quiskit.
4 |
--------------------------------------------------------------------------------
/archive/CnRy.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | from qiskit import *
4 | import matplotlib.pyplot as plt
5 |
6 |
7 | n = 5 # must be >= 2
8 |
9 | ctrl = QuantumRegister(n, 'ctrl')
10 | anc = QuantumRegister(n-1, 'anc')
11 | tgt = QuantumRegister(1, 'tgt')
12 |
13 | circ = QuantumCircuit(ctrl, anc, tgt)
14 |
15 | # compute
16 | circ.ccx(ctrl[0], ctrl[1], anc[0])
17 | for i in range(2, n):
18 | circ.ccx(ctrl[i], anc[i-2], anc[i-1])
19 |
20 | # copy
21 | circ.cx(anc[n-2], tgt[0])
22 |
23 | # uncompute
24 | for i in range(n-1, 1, -1):
25 | circ.ccx(ctrl[i], anc[i-2], anc[i-1])
26 | circ.ccx(ctrl[0], ctrl[1], anc[0])
27 |
28 | circ.draw(output='mpl')
29 | plt.show()
30 |
31 | '''ctrl = QuantumRegister(n, 'ctrl')
32 | anc = QuantumRegister(n-1, 'anc')
33 | tgt = QuantumRegister(1, 'tgt')
34 |
35 | circ = QuantumCircuit(ctrl, anc, tgt)
36 |
37 | circ.mct(ctrl, tgt[0], anc, mode='basic-dirty-ancilla')
38 | circ.draw(output='mpl')
39 | plt.show()
40 | '''
41 |
--------------------------------------------------------------------------------
/archive/byskit-old.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | from qiskit import *
4 |
5 | # First princinple for two parent nodes and one child
6 | class byskit():
7 | def __init__(self, provider, backend, n, parents, child):
8 | self.provider = provider
9 | self.backend = backend
10 | self.parents = parents
11 | self.child = child
12 | self.n = n
13 | self.ctrl = QuantumRegister(self.n, 'ctrl')
14 | self.anc = QuantumRegister(self.n - 1, 'anc')
15 | self.tgt = QuantumRegister(1, 'tgt')
16 | self.circ = QuantumCircuit(self.ctrl, self.anc, self.tgt)
17 |
18 | self.parent_init()
19 | self.child_init()
20 |
21 | self.circ.draw(output='mpl')
22 | plt.show()
23 |
24 | def parent_init(self):
25 | for i in range(self.n):
26 | theta = self.calc_theta(self.parents[2*i], self.parents[2*i+1])
27 | self.circ.ry(theta, i)
28 |
29 | self.circ.barrier()
30 |
31 | def child_init(self):
32 | self.a = np.arange(0, 2 ** self.n)
33 | self.gates = []
34 | for i in self.a:
35 | s = str(np.binary_repr(i, width=self.n))
36 | self.gates.append(s)
37 |
38 | for i in range(2**self.n):
39 | theta = self.calc_theta(self.child[2*i+1], self.child[2*i])
40 | self.xgate(self.gates[i])
41 | self.cn_ry(theta)
42 | self.xgate(self.gates[i])
43 | self.circ.barrier()
44 |
45 | def xgate(self,gate):
46 | for index, item in enumerate(gate):
47 | if int(item) == 0:
48 | self.circ.x(index)
49 |
50 | #RY gates
51 | def cn_ry(self,theta):
52 | # compute
53 | self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])
54 | for i in range(2, self.n):
55 | self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])
56 |
57 | # copy
58 | self.circ.cry(theta,self.anc[self.n - 2], self.tgt[0])
59 |
60 | # uncompute
61 | for i in range(self.n - 1, 1, -1):
62 | self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])
63 | self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])
64 |
65 |
66 | def calc_theta(self,p1,p0):
67 | return 2 * np.arctan(np.sqrt((p1)/(p0)))
68 |
69 |
70 | #if __name__=='__main__':
71 | from jupyterthemes import jtplot
72 |
73 | jtplot.style(theme='monokai', context='notebook', ticks=True, grid=False)
74 |
75 | from qiskit.tools.jupyter import *
76 | from qiskit import IBMQ
77 |
78 | IBMQ.load_account()
79 | # provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
80 | provider = IBMQ.get_provider(hub='ibm-q-oxford', group='on-boarding', project='on-boarding-proj')
81 | from qiskit import BasicAer
82 | backend = BasicAer.get_backend('unitary_simulator')
83 |
84 | n = 3
85 | parents = np.random.rand(n*2)
86 | child = np.random.rand(2**(n+1))
87 |
88 | b = byskit(provider,backend,n,parents,child)
--------------------------------------------------------------------------------
/archive/datastructure.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | class Vertex:
5 |
6 | def __init__(self, id, probabilities, child=False):
7 | # Identifier of the node
8 | self.id = id
9 |
10 | # Nodes that are parents of this
11 | self.parents = []
12 |
13 | # Nodes that are children of this
14 | self.children = []
15 |
16 | if child:
17 | assert not np.any(np.sum(probabilities, axis=1) - 1)
18 |
19 | self.probabilities = probabilities
20 |
21 | def __str__(self):
22 | return self.id
23 |
24 | def add_child(self, child):
25 | self.children.extend(child)
26 |
27 | def add_parent(self, parent):
28 | self.parents.extend(parent)
29 |
30 | def get_direct_children(self):
31 | return self.children
32 |
33 | def get_all_children(self):
34 | # recursively get_direct_children
35 | pass
36 |
37 |
38 | class Bayesnet:
39 |
40 | def __init__(self):
41 | self.vertex_dictionary = {}
42 | self.number_vertices = 0
43 |
44 | def __iter__(self):
45 | return iter(self.vertex_dictionary.values())
46 |
47 | def __call__(self, id):
48 | return self.vertex_dictionary[id]
49 |
50 | def add_root(self, name, probabilities):
51 | new_root = Vertex(name, probabilities)
52 | self.vertex_dictionary[name] = new_root
53 |
54 | def get_vertex(self, node):
55 | if node in self.vertex_dictionary:
56 | return self.vertex_dictionary[node]
57 | else:
58 | return None
59 |
60 | def add_child(self, id, parents, probability_table):
61 | child = Vertex(id, probability_table, child=True)
62 |
63 | child.add_parent(parents)
64 |
65 | self.vertex_dictionary[id] = child
66 | self.number_vertices += 1
67 |
68 | for parent in parents:
69 | self.vertex_dictionary[parent].add_child(child.id)
70 |
71 |
72 | if __name__ == '__main__':
73 | net = Bayesnet()
74 |
75 | net.add_root('A', [0.2, 0.8])
76 | net.add_root('B', [0.3, 0.7])
77 |
78 | net.add_child('C', ['A', 'B'], np.array([[0.15, 0.3, 0.4, 0.1], [0.85, 0.7, 0.6, 0.9]]).T)
79 |
80 | print(net('C').parents)
81 | print(net('A').probabilities[0])
82 |
83 | print("conditional prob of child: ", net('C').probabilities[0, 0])
84 |
--------------------------------------------------------------------------------
/archive/fig5.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | from qiskit import *
4 |
5 | # First princinple for two parent nodes and one child
6 | class byskit():
7 | def __init__(self, provider, backend, n, parents, child):
8 | self.provider = provider
9 | self.backend = backend
10 | self.parents = parents
11 | self.child = child
12 | self.n = n
13 | self.ctrl = QuantumRegister(self.n, 'ctrl')
14 | self.anc = QuantumRegister(self.n - 1, 'anc')
15 | self.tgt = QuantumRegister(1, 'tgt')
16 | self.circ = QuantumCircuit(self.ctrl, self.anc, self.tgt)
17 |
18 | self.parent_init()
19 | self.child_init()
20 |
21 | self.circ.draw(output='mpl')
22 | plt.show()
23 |
24 | def parent_init(self):
25 | for i in range(self.n):
26 | theta = self.calc_theta(self.parents[2*i], self.parents[2*i+1])
27 | self.circ.ry(theta, i)
28 |
29 | self.circ.barrier()
30 | self.circ.x(self.ctrl)
31 |
32 | def child_init(self):
33 | self.a = np.arange(0, 2 ** self.n)
34 | gates = []
35 | for i in self.a:
36 | s = str(np.binary_repr(i, width=self.n))
37 | gates.append(s)
38 |
39 | for i in range(2*self.n):
40 | theta = self.calc_theta(self.child[2*i+1], self.child[2*i])
41 |
42 | for index2,item2 in enumerate(gates[i]):
43 | print(item2)
44 | if int(item2) == 0:
45 | self.circ.x(index2)
46 |
47 | self.cn_ry(theta)
48 |
49 | for index2,item2 in enumerate(gates[i]):
50 | print(item2)
51 | if int(item2) == 0:
52 | self.circ.x(index2)
53 |
54 | self.circ.barrier()
55 |
56 |
57 |
58 | #RY gates
59 | def cn_ry(self,theta):
60 | # compute
61 | self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])
62 | for i in range(2, self.n):
63 | self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])
64 |
65 | # copy
66 | self.circ.cry(theta,self.anc[self.n - 2], self.tgt[0])
67 |
68 | # uncompute
69 | for i in range(self.n - 1, 1, -1):
70 | self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])
71 | self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])
72 |
73 |
74 | def calc_theta(self,p1,p0):
75 | return 2 * np.arctan(np.sqrt((p1)/(p0)))
76 |
77 |
78 | if __name__=='__main__':
79 | from jupyterthemes import jtplot
80 |
81 | jtplot.style(theme='monokai', context='notebook', ticks=True, grid=False)
82 |
83 | from qiskit.tools.jupyter import *
84 | from qiskit import IBMQ
85 |
86 | IBMQ.load_account()
87 | # provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
88 | provider = IBMQ.get_provider(hub='ibm-q-oxford', group='on-boarding', project='on-boarding-proj')
89 | from qiskit import BasicAer
90 | backend = BasicAer.get_backend('unitary_simulator')
91 |
92 | a0 = 0.2
93 | a1 = 0.8
94 | b0 = 0.3
95 | b1 = 0.7
96 | c000 = 0.15
97 | c001 = 0.3
98 | c010 = 0.4
99 | c011 = 0.1
100 | c100 = 0.85
101 | c101 = 0.7
102 | c110 = 0.6
103 | c111 = 0.9
104 |
105 |
106 |
107 | parents = np.array([a0,a1,b0,b1])
108 | child = np.array([c000,c100,c001,c101,c010,c110,c011,c111])
109 | n = 2
110 |
111 | b = byskit(provider,backend,n,parents,child)
112 |
113 | print(np.shape(b.parents))
114 | print(np.shape(b.child))
--------------------------------------------------------------------------------
/byskit-two-layer.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | from qiskit import *
4 | from qiskit.aqua.algorithms import Grover
5 |
6 |
7 | # First princinple for two parent nodes and one child
8 | class byskit():
9 | def __init__(self, backend, parents, child, evd = None):
10 | self.backend = backend
11 | self.parents = parents
12 | self.child = child
13 | self.n = int(np.shape(parents)[0]/2)
14 | self.n_child = np.shape(child)[1]
15 | self.ctrl = QuantumRegister(self.n, 'ctrl')
16 | self.anc = QuantumRegister(self.n - 1, 'anc')
17 | self.tgt = QuantumRegister(self.n_child, 'tgt')
18 | if evd != None:
19 | self.oracle = QuantumRegister(evd,'oracle')
20 | self.circ = QuantumCircuit(self.ctrl, self.anc, self.tgt, self.oracle)
21 | else:
22 | self.circ = QuantumCircuit(self.ctrl, self.anc, self.tgt)
23 |
24 | #self.c_ctrl = ClassicalRegister(self.n, 'c_ctrl')
25 | #self.c_tgt = ClassicalRegister(self.n_child, 'c_tgt')
26 |
27 | self.parent_init()
28 | self.child_init()
29 |
30 | def parent_init(self):
31 | for i in range(self.n):
32 | theta = self.calc_theta(self.parents[2*i], self.parents[2*i+1])
33 | self.circ.ry(theta, i)
34 |
35 | self.circ.barrier()
36 |
37 | def child_init(self):
38 | self.a = np.arange(0, 2 ** self.n)
39 | self.gates = []
40 | for i in self.a:
41 | s = str(np.binary_repr(i, width=self.n))
42 | self.gates.append(s)
43 |
44 | for i in range(2**self.n):
45 | self.xgate(self.gates[i])
46 | for j in range(self.n_child):
47 | theta = self.calc_theta(self.child[2 * i + 1,j], self.child[2 * i,j])
48 | self.cn_ry(theta,j)
49 | self.xgate(self.gates[i])
50 | self.circ.barrier()
51 |
52 | def xgate(self,gate):
53 | for index, item in enumerate(gate):
54 | if int(item) == 0:
55 | self.circ.x(index)
56 |
57 | #RY gates
58 | def cn_ry(self,theta,target):
59 | # compute
60 | self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])
61 | for i in range(2, self.n):
62 | self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])
63 |
64 | # copy
65 | self.circ.cry(theta,self.anc[self.n - 2], self.tgt[target])
66 |
67 | # uncompute
68 | for i in range(self.n - 1, 1, -1):
69 | self.circ.ccx(self.ctrl[i], self.anc[i - 2], self.anc[i - 1])
70 | self.circ.ccx(self.ctrl[0], self.ctrl[1], self.anc[0])
71 |
72 |
73 | def calc_theta(self,p1,p0):
74 | return 2 * np.arctan(np.sqrt((p1)/(p0)))
75 |
76 | def plot(self):
77 | self.circ.draw(output='mpl')
78 | plt.show()
79 |
80 | def execute_circ(self):
81 | self.circ.measure_all()
82 | results = execute(self.circ, self.backend, shots=4321)
83 | return results
84 |
85 | def rejection_sampling(self, evidence, shots=1000, amplitude_amplification=False):
86 | # Run job many times to get multiple samples
87 | samples_list = []
88 | self.n_samples = shots
89 |
90 | if amplitude_amplification==True:
91 | self.amplitude_amplification(evidence)
92 |
93 | self.circ.measure_all()
94 |
95 | #self.circ.measure((self.ctrl, self.tgt),(self.c_ctrl, self.c_tgt))
96 |
97 | for i in range(self.n_samples):
98 | job = execute(self.circ, backend=self.backend, shots=1)
99 | result = list(job.result().get_counts(self.circ).keys())[0]
100 | accept = True
101 | for e in evidence:
102 | if result[evidence[e]['n']]==evidence[e]['state']:
103 | pass
104 | else:
105 | accept=False
106 | if accept == True:
107 | #print('Accepted result ', result)
108 | samples_list.append(result)
109 |
110 | print()
111 | print(self.n_samples, 'samples drawn:', len(samples_list), 'samples accepted,', self.n_samples - len(samples_list),
112 | 'samples rejected.')
113 | print('Percentage of samples rejected: ', 100 * (1 - (len(samples_list) / self.n_samples)), '%')
114 |
115 | return samples_list
116 |
117 |
118 | def evaluate(self, samples_list, observations):
119 | p_o = 0
120 | for sample in samples_list:
121 | accept = True
122 | for o in observations:
123 | if sample[observations[o]['n']] == observations[o]['state']:
124 | pass
125 | else:
126 | accept = False
127 | if accept == True:
128 | #print('Observation true given evidence')
129 | p_o += 1
130 | p_o /= len(samples_list)
131 |
132 | print('Probabilty of observations given evidence = ', p_o)
133 |
134 | return p_o
135 |
136 | def amplitude_amplification(self,evidence):
137 | self.state_preparation = self.circ
138 | self.oracle = QuantumCircuit(self.ctrl, self.anc, self.tgt)
139 | for index, e in enumerate(evidence):
140 | if evidence[e]['state'] == '1':
141 | self.oracle.z([evidence[e]['n']])
142 |
143 | self.grover_op = Grover(self.oracle, state_preparation=self.state_preparation)
144 | self.grover_op.draw()
145 |
146 | def oracle(self):
147 | pass
148 |
149 | def u_gate(self):
150 | pass
151 |
152 | def gen_random_weights(n_parent,n_child):
153 | np.random.seed(0)
154 | p = np.random.rand(n_parent)
155 | parents = []
156 | for i in p:
157 | parents.append(i)
158 | parents.append(1 - i)
159 | parents = np.array(parents)
160 |
161 | child = np.random.rand(2 ** (n_parent + 1), n_child)
162 | for i in range(n_child):
163 | for j in range(2 ** (n_parent)):
164 | child[2 * j + 1, i] = 1 - child[2 * j, i]
165 |
166 | return parents, child
167 |
168 | if __name__=='__main__':
169 | from qiskit import IBMQ
170 |
171 |
172 | IBMQ.load_account()
173 | #provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
174 | provider = IBMQ.get_provider(hub='ibm-q-oxford', group='on-boarding', project='on-boarding-proj')
175 | from qiskit import Aer #BasicAer
176 | #backend = BasicAer.get_backend('unitary_simulator')
177 | backend = Aer.get_backend('qasm_simulator')
178 |
179 | n_parent = 3
180 | n_child = 3
181 |
182 | parents, children = gen_random_weights(n_parent, n_child)
183 | b = byskit(backend, parents, children)
184 | b.plot()
185 |
186 | evidence = {
187 | 'one':{
188 | 'n':1,
189 | 'state':'1'
190 | }
191 | }
192 | #b.rejection_sampling(evidence,amplitude_amplification=True)
193 | sample_list = b.rejection_sampling(evidence)
194 |
195 | observations = {
196 | 'three':{
197 | 'n':2,
198 | 'state':'0'
199 | }
200 | }
201 |
202 | prob = b.evaluate(sample_list, observations)
--------------------------------------------------------------------------------
/byskit.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import matplotlib.pyplot as plt
3 | from qiskit import *
4 | from qiskit.aqua.algorithms import Grover
5 |
6 |
7 | # First princinple for two parent nodes and one child
8 | class byskit():
9 | def __init__(self, backend,network, loaded_net, evd = None):
10 | self.backend = backend
11 | self.network = network
12 | self.net_keys = [key for key in self.network]
13 | self.loaded_net = loaded_net
14 | self.reg = {}
15 |
16 | self.create_circ()
17 |
18 | self.root_init()
19 |
20 | child_index = np.array([0,0])
21 | parent_index = np.array([0, 0])
22 | for index in range(len(self.net_keys)-1):
23 | parent_key = self.net_keys[index]
24 | child_key = self.net_keys[index+1]
25 | if parent_key != 'root':
26 | parent_index = np.array([parent_index[1], parent_index[1] + self.network[self.net_keys[index + 1]]])
27 | child_index = np.array([child_index[1],child_index[1]+self.network[self.net_keys[index+1]]])
28 | self.child_init(parent_key,parent_index,child_key,child_index)
29 |
30 | def create_circ(self):
31 | self.n_anc = 0
32 | self.n_tgt = 0
33 | for key in self.network:
34 | if key == 'root':
35 | n = self.network['root']
36 | self.reg['cntrl'] = QuantumRegister(self.network['root'], 'cntrl')
37 |
38 | else:
39 | self.n_anc = max(n-1,self.n_anc)
40 | self.n_tgt += self.network[key]
41 | n = self.network[key]
42 | self.reg['anc'] = QuantumRegister(self.n_anc,'anc')
43 | self.reg['tgt'] = QuantumRegister(self.n_tgt, 'tgt')
44 |
45 | self.circ = QuantumCircuit(self.reg['cntrl'],self.reg['anc'],self.reg['tgt'])
46 |
47 |
48 | def root_init(self):
49 | for i in range(self.network['root']):
50 | theta = self.calc_theta(self.loaded_net['root'][2*i], self.loaded_net['root'][2*i+1])
51 | self.circ.ry(theta, i)
52 |
53 | self.circ.barrier()
54 |
55 | def child_init(self,parent_key,parent_index,child_key,child_index):
56 | parent_index = parent_index[0]
57 | child_index = child_index[0]
58 | self.a = np.arange(0, 2 ** self.network[parent_key])
59 | self.gates = []
60 | for i in self.a:
61 | s = str(np.binary_repr(i, width=self.network[parent_key]))
62 | self.gates.append(s)
63 |
64 | for i in range(2**self.network[parent_key]):
65 | self.xgate(self.gates[i],parent_index)
66 | for j in range(self.network[child_key]):
67 | theta = self.calc_theta(self.loaded_net[child_key][2 * i + 1,j], self.loaded_net[child_key][2 * i,j])
68 | self.cn_ry(theta,j,parent_key,parent_index,child_key,child_index)
69 | self.xgate(self.gates[i],parent_index)
70 | self.circ.barrier()
71 |
72 | def xgate(self,gate,parent_index):
73 | for index, item in enumerate(gate):
74 | if int(item) == 0:
75 | self.circ.x(index+parent_index)
76 |
77 | #RY gates
78 | def cn_ry(self,theta,target,parent_key,parent_index,child_key,child_index):
79 | # compute
80 | if parent_key == 'root':
81 | self.circ.ccx(self.reg['cntrl'][0], self.reg['cntrl'][1], self.reg['anc'][0])
82 | for i in range(2, self.network[parent_key]):
83 | self.circ.ccx(self.reg['cntrl'][i], self.reg['anc'][i - 2], self.reg['anc'][i - 1])
84 |
85 | # copy
86 | self.circ.cry(theta,self.reg['anc'][self.network[parent_key] - 2], self.reg['tgt'][target])
87 |
88 | # uncompute
89 | for i in range(self.network[parent_key] - 1, 1, -1):
90 | self.circ.ccx(self.reg['cntrl'][i], self.reg['anc'][i - 2], self.reg['anc'][i - 1])
91 | self.circ.ccx(self.reg['cntrl'][0], self.reg['cntrl'][1], self.reg['anc'][0])
92 |
93 | else:
94 | self.circ.ccx(self.reg['tgt'][parent_index+0], self.reg['tgt'][parent_index+1], self.reg['anc'][0])
95 | for i in range(2, self.network[parent_key]):
96 | self.circ.ccx(self.reg['tgt'][parent_index+i], self.reg['anc'][i - 2], self.reg['anc'][i - 1])
97 |
98 | # copy
99 | self.circ.cry(theta,self.reg['anc'][self.network[parent_key] - 2], self.reg['tgt'][child_index+target])
100 |
101 | # uncompute
102 | for i in range(self.network[parent_key] - 1, 1, -1):
103 | self.circ.ccx(self.reg['tgt'][parent_index+i], self.reg['anc'][i - 2], self.reg['anc'][i - 1])
104 | self.circ.ccx(self.reg['tgt'][parent_index+0], self.reg['tgt'][parent_index+1], self.reg['anc'][0])
105 |
106 | def calc_theta(self,p1,p0):
107 | return 2 * np.arctan(np.sqrt((p1)/(p0)))
108 |
109 | def plot(self):
110 | self.circ.draw(output='mpl')
111 | plt.show()
112 |
113 | def execute_circ(self):
114 | self.circ.measure_all()
115 | results = execute(self.circ, self.backend, shots=4321)
116 | return results
117 |
118 | def rejection_sampling(self, evidence, shots=5000, amplitude_amplification=False):
119 | # Run job many times to get multiple samples
120 | samples_list = []
121 | self.n_samples = shots
122 |
123 | if amplitude_amplification==True:
124 | self.amplitude_amplification(evidence)
125 |
126 | self.circ.measure_all()
127 |
128 | for i in range(self.n_samples):
129 | job = execute(self.circ, backend=self.backend, shots=1)
130 | result = list(job.result().get_counts(self.circ).keys())[0]
131 | accept = True
132 | for e in evidence:
133 | if result[evidence[e]['n']]==evidence[e]['state']:
134 | pass
135 | else:
136 | accept=False
137 | if accept == True:
138 | #print('Accepted result ', result)
139 | samples_list.append(result)
140 |
141 | print()
142 | print(self.n_samples, 'samples drawn:', len(samples_list), 'samples accepted,', self.n_samples - len(samples_list),
143 | 'samples rejected.')
144 | print('Percentage of samples rejected: ', 100 * (1 - (len(samples_list) / self.n_samples)), '%')
145 |
146 | return samples_list
147 |
148 |
149 | def evaluate(self, samples_list, observations):
150 | p_o = 0
151 | for sample in samples_list:
152 | accept = True
153 | for o in observations:
154 | if sample[observations[o]['n']] == observations[o]['state']:
155 | pass
156 | else:
157 | accept = False
158 | if accept == True:
159 | #print('Observation true given evidence')
160 | p_o += 1
161 | p_o /= len(samples_list)
162 |
163 | print('Probabilty of observations given evidence = ', p_o)
164 |
165 | return p_o
166 |
167 | def amplitude_amplification(self,evidence):
168 | self.state_preparation = self.circ
169 | self.oracle = QuantumCircuit(self.ctrl, self.anc, self.tgt)
170 | for index, e in enumerate(evidence):
171 | if evidence[e]['state'] == '1':
172 | self.oracle.z([evidence[e]['n']])
173 |
174 | self.grover_op = Grover(self.oracle, state_preparation=self.state_preparation)
175 | self.grover_op.draw()
176 |
177 | def oracle(self):
178 | pass
179 |
180 | def u_gate(self):
181 | pass
182 |
183 | def gen_random_net(network):
184 | np.random.seed(0)
185 | loaded_net = {}
186 | for key in network:
187 | if key == 'root':
188 | n_parent = network[key]
189 | p = np.random.rand(n_parent)
190 | parents = []
191 | for i in p:
192 | parents.append(i)
193 | parents.append(1 - i)
194 | loaded_net[key] = np.array(parents)
195 |
196 | else:
197 | n_child = network[key]
198 | child = np.random.rand(2 ** (n_parent + 1), n_child)
199 |
200 | for i in range(n_child):
201 | for j in range(2 ** (n_parent)):
202 | child[2 * j + 1, i] = 1 - child[2 * j, i]
203 |
204 | loaded_net[key] = child
205 |
206 | n_parent = n_child
207 |
208 | return loaded_net
209 |
210 |
211 | if __name__=='__main__':
212 | from qiskit import IBMQ
213 | IBMQ.load_account()
214 | #provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
215 | provider = IBMQ.get_provider(hub='ibm-q-oxford', group='on-boarding', project='on-boarding-proj')
216 | from qiskit import Aer #BasicAer
217 | #backend = BasicAer.get_backend('unitary_simulator')
218 | backend = Aer.get_backend('qasm_simulator')
219 |
220 | #network = {'root':2,'child-1':3,'child-2':3,'child-3':2}
221 | network = {'root':2,'child-1':3,'child-2':3}
222 |
223 | loaded_net = gen_random_net(network)
224 | b = byskit(backend, network, loaded_net)
225 | b.plot()
226 |
227 | evidence = {
228 | 'one':{
229 | 'n':1,
230 | 'state':'1'
231 | },
232 | 'two':{
233 | 'n':5,
234 | 'state':'0'
235 | }
236 | }
237 | #b.rejection_sampling(evidence,amplitude_amplification=True)
238 | sample_list = b.rejection_sampling(evidence, shots=1000,amplitude_amplification=False)
239 |
240 | observations = {
241 | 'one':{
242 | 'n':2,
243 | 'state':'0'
244 | },
245 | 'two': {
246 | 'n': 4,
247 | 'state': '1'
248 | }
249 | }
250 |
251 | prob = b.evaluate(sample_list, observations)
252 |
253 |
254 | from qiskit import IBMQ
255 | IBMQ.load_account()
256 | provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')
257 |
258 | from qiskit import Aer
259 | backend = Aer.get_backend('qasm_simulator')
260 |
261 | network = {'root':2,'child-1':3,'child-2':3}
262 | loaded_net = gen_random_net(network)
263 | b = byskit(backend, network, loaded_net)
264 | b.plot()
265 |
266 | evidence = {
267 | 'one':{
268 | 'n':1,
269 | 'state':'1'
270 | },
271 | 'two':{
272 | 'n':5,
273 | 'state':'0'
274 | }
275 | }
276 |
277 | sample_list = b.rejection_sampling(evidence, shots=1000, amplitude_amplification=True)
278 |
279 | observations = {
280 | 'one':{
281 | 'n':2,
282 | 'state':'0'
283 | },
284 | 'two': {
285 | 'n': 4,
286 | 'state': '1'
287 | }
288 | }
289 |
290 | prob = b.evaluate(sample_list, observations)
--------------------------------------------------------------------------------
/presentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mlvqc/Byskit/bddf9834e29fea0f19b39a2e331201d17aabc6f1/presentation.pdf
--------------------------------------------------------------------------------
/test.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [
8 | {
9 | "name": "stderr",
10 | "output_type": "stream",
11 | "text": [
12 | "/home/sebastian/anaconda/envs/Quiskit/lib/python3.8/site-packages/qiskit/providers/ibmq/ibmqfactory.py:192: UserWarning: Timestamps in IBMQ backend properties, jobs, and job results are all now in local time instead of UTC.\n",
13 | " warnings.warn('Timestamps in IBMQ backend properties, jobs, and job results '\n"
14 | ]
15 | }
16 | ],
17 | "source": [
18 | "from jupyterthemes import jtplot\n",
19 | "jtplot.style(theme='monokai', context='notebook', ticks=True, grid=False)\n",
20 | "\n",
21 | "from qiskit.tools.jupyter import *\n",
22 | "from qiskit import IBMQ\n",
23 | "IBMQ.load_account()\n",
24 | "#provider = IBMQ.get_provider(hub='ibm-q', group='open', project='main')\n",
25 | "provider = IBMQ.get_provider(hub='ibm-q-oxford', group='on-boarding', project='on-boarding-proj') \n",
26 | "\n",
27 | "from qiskit import QuantumCircuit, ClassicalRegister, QuantumRegister, execute\n",
28 | "from qiskit.tools.visualization import circuit_drawer\n",
29 | "from qiskit.quantum_info import state_fidelity\n",
30 | "from qiskit import BasicAer\n",
31 | "\n",
32 | "backend = BasicAer.get_backend('unitary_simulator')"
33 | ]
34 | },
35 | {
36 | "cell_type": "markdown",
37 | "metadata": {},
38 | "source": []
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": 2,
43 | "metadata": {},
44 | "outputs": [
45 | {
46 | "data": {
47 | "image/png": "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\n",
48 | "text/plain": [
49 | ""
50 | ]
51 | },
52 | "execution_count": 2,
53 | "metadata": {},
54 | "output_type": "execute_result"
55 | }
56 | ],
57 | "source": [
58 | "# Useful additional packages \n",
59 | "import matplotlib.pyplot as plt\n",
60 | "%matplotlib inline\n",
61 | "import numpy as np\n",
62 | "from math import pi\n",
63 | "\n",
64 | "q = QuantumRegister(1)\n",
65 | "qc = QuantumCircuit(q)\n",
66 | "qc.u3(pi/2,pi/2,pi/2,q)\n",
67 | "qc.draw(output='mpl')"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": 3,
73 | "metadata": {},
74 | "outputs": [
75 | {
76 | "data": {
77 | "text/plain": [
78 | "array([[ 7.07106781e-01+0.00000000e+00j, -4.32978028e-17-7.07106781e-01j],\n",
79 | " [ 4.32978028e-17+7.07106781e-01j, -7.07106781e-01+8.65956056e-17j]])"
80 | ]
81 | },
82 | "execution_count": 3,
83 | "metadata": {},
84 | "output_type": "execute_result"
85 | }
86 | ],
87 | "source": [
88 | "job = execute(qc, backend)\n",
89 | "job.result().get_unitary(qc, decimals=3)"
90 | ]
91 | },
92 | {
93 | "cell_type": "code",
94 | "execution_count": 4,
95 | "metadata": {},
96 | "outputs": [
97 | {
98 | "name": "stdout",
99 | "output_type": "stream",
100 | "text": [
101 | "ibmq_qasm_simulator has 3 queued and simulated qubits\n",
102 | "ibmq_16_melbourne has 38 queued and 15 qubits\n",
103 | "ibmq_vigo has 28 queued and 5 qubits\n",
104 | "ibmq_ourense has 23 queued and 5 qubits\n",
105 | "ibmq_valencia has 17 queued and 5 qubits\n",
106 | "ibmq_rochester has 15 queued and 53 qubits\n",
107 | "ibmq_armonk has 12 queued and 1 qubits\n",
108 | "ibmq_cambridge has 6 queued and 28 qubits\n",
109 | "ibmq_paris has 30 queued and 27 qubits\n",
110 | "ibmq_rome has 23 queued and 5 qubits\n",
111 | "ibmq_toronto has 53 queued and 27 qubits\n",
112 | "ibmq_santiago has 27 queued and 5 qubits\n",
113 | "ibmq_bogota has 8 queued and 5 qubits\n",
114 | "ibmq_manhattan has 9 queued and 65 qubits\n"
115 | ]
116 | }
117 | ],
118 | "source": [
119 | "for backend in provider.backends():\n",
120 | " try:\n",
121 | " qubit_count = len(backend.properties().qubits)\n",
122 | " except:\n",
123 | " qubit_count = 'simulated'\n",
124 | " print('{} has {} queued and {} qubits'.format(backend.name(),backend.status().pending_jobs,qubit_count) )"
125 | ]
126 | },
127 | {
128 | "cell_type": "markdown",
129 | "metadata": {},
130 | "source": [
131 | "## Bayes net (i)\n",
132 | "P(A = 0) = 0.2\n",
133 | "\n",
134 | "P(A = 1) = 0.8\n",
135 | "\n",
136 | "\n",
137 | "P(B = 0) = 0.3\n",
138 | "\n",
139 | "P(B = 1) = 0.7\n",
140 | "\n",
141 | "\n",
142 | "\n",
143 | "P(C = 0|A=0,B=0) = 0.15\n",
144 | "\n",
145 | "P(C = 0|A=0,B=1) = 0.3\n",
146 | "\n",
147 | "P(C = 0|A=1,B=0) = 0.4\n",
148 | "\n",
149 | "P(C = 0|A=1,B=1) = 0.1\n",
150 | "\n",
151 | "\n",
152 | "\n",
153 | "P(C = 1|A=0,B=0) = 0.85\n",
154 | "\n",
155 | "P(C = 1|A=0,B=1) = 0.7\n",
156 | "\n",
157 | "P(C = 1|A=1,B=0) = 0.6\n",
158 | "\n",
159 | "P(C = 1|A=1,B=1) = 0.9"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {},
165 | "source": [
166 | "### Rotation angle computation\n",
167 | "By applying an RY-gate with an appropriate angle, the probabilities of the root node can be mapped to the probabilities (and thus probability amplitudes) of the basis states.\n",
168 | "Two-state root nodes can we represented by an RY gate with rotation angle $ = 2*tan^{-1}\\sqrt{\\frac{P(V_{i}=1)}{P(V_{i}=0)})}$.\n",
169 | "\n"
170 | ]
171 | },
172 | {
173 | "cell_type": "markdown",
174 | "metadata": {},
175 | "source": [
176 | "Therefore, for Bayes net (i), the rotation angles are $\\theta_{A} = 2*tan^{-1}(\\frac{0.8}{0.2}) = 2.214$ and $\\theta_{B} = 2*tan^{-1}(\\frac{0.7}{0.3}) = 1.982$."
177 | ]
178 | },
179 | {
180 | "cell_type": "markdown",
181 | "metadata": {},
182 | "source": [
183 | "For the child nodes,\n",
184 | "\\begin{equation}\n",
185 | "\\theta_{V_{i},\\Pi_{V_{I}}^{*}} = 2 * tan^{-1}\\left(\\sqrt{\\frac{P(V_{i}=1|\\Pi_{V_{i}}=\\Pi_{V_{i}}^{*})}{P(V_{i}=0|\\Pi_{V_{i}}=\\Pi_{V_{i}}^{*})}}\\right)\n",
186 | "\\end{equation}\n",
187 | "\n",
188 | " The conditional probabilities associated with childnodes are realized through controlled rotations. "
189 | ]
190 | },
191 | {
192 | "cell_type": "markdown",
193 | "metadata": {},
194 | "source": [
195 | "Thus,\n",
196 | "\n",
197 | "$\\theta(C|A=0,B=0) = 2.348$\n",
198 | "\n",
199 | "$\\theta(C|A=0,B=1) = 1.982$\n",
200 | "\n",
201 | "$\\theta(C|A=1,B=0) = 1.772$\n",
202 | "\n",
203 | "$\\theta(C|A=1,B=1) = 2.498$\n",
204 | "\n",
205 | "\n",
206 | "\n"
207 | ]
208 | },
209 | {
210 | "cell_type": "code",
211 | "execution_count": null,
212 | "metadata": {},
213 | "outputs": [],
214 | "source": []
215 | }
216 | ],
217 | "metadata": {
218 | "kernelspec": {
219 | "display_name": "Python 3",
220 | "language": "python",
221 | "name": "python3"
222 | },
223 | "language_info": {
224 | "codemirror_mode": {
225 | "name": "ipython",
226 | "version": 3
227 | },
228 | "file_extension": ".py",
229 | "mimetype": "text/x-python",
230 | "name": "python",
231 | "nbconvert_exporter": "python",
232 | "pygments_lexer": "ipython3",
233 | "version": "3.8.5"
234 | }
235 | },
236 | "nbformat": 4,
237 | "nbformat_minor": 4
238 | }
239 |
--------------------------------------------------------------------------------