From b887f27a555fa51d457aa5a3ea5e5c8c0286b045 Mon Sep 17 00:00:00 2001 From: Fernando Date: Tue, 26 Jun 2018 12:27:48 +0200 Subject: [PATCH 01/29] First testing version of Phase Estimation with a lot of hardcoding --- examples/phase_estimation.py | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 examples/phase_estimation.py diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py new file mode 100644 index 000000000..0d38f4527 --- /dev/null +++ b/examples/phase_estimation.py @@ -0,0 +1,60 @@ +from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse, Measure, C, T, S, Tdag, Sdag +from projectq import MainEngine + +def phase_estimation(eng,unitary,eigenvector,n_ancillas): + + # create the ancillas and are left to |0> + ancilla = eng.allocate_qureg(n_ancillas) + + # Hadamard on the ancillas + Tensor(H) | ancilla + + # Control U on the eigenvector + # Por ahora solo funciona con unitary = X ************* + unitario = X # ****** unitary + for i in range(n_ancillas): + if i %2 == 0: + C(unitario) | (ancilla[i],eigenvector[0]) + else: + pass + + # Inverse QFT on the ancilla + get_inverse(QFT) | ancilla + + # Ancilla measurement + Measure | ancilla + + # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) + fasebinlist = [int(q) for q in ancilla] + print (fasebinlist, type(fasebinlist)) + + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin,2) + fase = faseint / (2 ** n_ancillas) + + print (fasebin, faseint,"fase final = ", fase) + return fase + + + +if __name__ == "__main__": + #Create the compiler engine + eng = MainEngine() + + # Create the Unitary Operator and the eigenvector + unitario = X + autovector = eng.allocate_qureg(1) + X | autovector[0] + H | autovector[0] + + # Ask for the number of ancillas to use + ene = int(input("How many ancillas?: ")) + # Call the phase_estimation function + fase = phase_estimation(eng,unitario,autovector,ene) + + + # Deferred measure del estado para que pueda imprimir cosas + + Measure | autovector + + eng.flush() From c13e2f3e819ead7a6928e946d60d0dbcde5fa98c Mon Sep 17 00:00:00 2001 From: Fernando Date: Tue, 26 Jun 2018 12:49:38 +0200 Subject: [PATCH 02/29] Adapt to All(Measure) --- examples/phase_estimation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 0d38f4527..ecfc375c1 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -1,4 +1,4 @@ -from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse, Measure, C, T, S, Tdag, Sdag +from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse, All, Measure, C, T, S, Tdag, Sdag from projectq import MainEngine def phase_estimation(eng,unitary,eigenvector,n_ancillas): @@ -22,7 +22,7 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): get_inverse(QFT) | ancilla # Ancilla measurement - Measure | ancilla + All(Measure) | ancilla # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) fasebinlist = [int(q) for q in ancilla] @@ -55,6 +55,6 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): # Deferred measure del estado para que pueda imprimir cosas - Measure | autovector + All(Measure) | autovector eng.flush() From bb5fb5708979a208aac5023180b3b0a9ca9c3658 Mon Sep 17 00:00:00 2001 From: Fernando Date: Tue, 26 Jun 2018 14:56:38 +0200 Subject: [PATCH 03/29] Adding operators for more than 1 quibit, first version --- examples/phase_estimation.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index ecfc375c1..867c849d1 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -1,4 +1,4 @@ -from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse, All, Measure, C, T, S, Tdag, Sdag +from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse, All, Measure, QubitOperator, C, T, S, Tdag, Sdag from projectq import MainEngine def phase_estimation(eng,unitary,eigenvector,n_ancillas): @@ -10,13 +10,12 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): Tensor(H) | ancilla # Control U on the eigenvector - # Por ahora solo funciona con unitary = X ************* - unitario = X # ****** unitary + unitario = unitary + for i in range(n_ancillas): - if i %2 == 0: - C(unitario) | (ancilla[i],eigenvector[0]) - else: - pass + C(unitario) | (ancilla[i],eigenvector) + for j in range(i): + C(unitario) | (ancilla[i],eigenvector) # Inverse QFT on the ancilla get_inverse(QFT) | ancilla @@ -42,10 +41,11 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): eng = MainEngine() # Create the Unitary Operator and the eigenvector - unitario = X - autovector = eng.allocate_qureg(1) - X | autovector[0] - H | autovector[0] + unitario = QubitOperator('X0 X1') + #unitario = X + autovector = eng.allocate_qureg(2) + X | autovector[1] + All(H) | autovector # Ask for the number of ancillas to use ene = int(input("How many ancillas?: ")) From 6a18cbfc75f8886cbb5ac266f6c86ab6b191e3b5 Mon Sep 17 00:00:00 2001 From: Fernando Date: Tue, 26 Jun 2018 17:02:37 +0200 Subject: [PATCH 04/29] Adding operators for more than 1 quibit, first versioni: testing --- examples/phase_estimation.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 867c849d1..35f17a02c 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -1,4 +1,6 @@ -from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse, All, Measure, QubitOperator, C, T, S, Tdag, Sdag +from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse +from projectq.ops import All, Measure, QubitOperator, TimeEvolution +from projectq.meta import Control from projectq import MainEngine def phase_estimation(eng,unitary,eigenvector,n_ancillas): @@ -13,9 +15,11 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): unitario = unitary for i in range(n_ancillas): - C(unitario) | (ancilla[i],eigenvector) + with Control(eng,ancilla[i]): + unitario | eigenvector for j in range(i): - C(unitario) | (ancilla[i],eigenvector) + with Control(eng,ancilla[i]): + unitario | eigenvector # Inverse QFT on the ancilla get_inverse(QFT) | ancilla @@ -43,6 +47,9 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): # Create the Unitary Operator and the eigenvector unitario = QubitOperator('X0 X1') #unitario = X + + unit = TimeEvolution(1.0,unitario) + autovector = eng.allocate_qureg(2) X | autovector[1] All(H) | autovector @@ -50,8 +57,21 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): # Ask for the number of ancillas to use ene = int(input("How many ancillas?: ")) # Call the phase_estimation function - fase = phase_estimation(eng,unitario,autovector,ene) + fase = phase_estimation(eng,unit,autovector,ene) +#======== Testing ==== + + #unit | autovector + eng.flush() + amp_after1 = eng.backend.get_amplitude('00', autovector) + amp_after2 = eng.backend.get_amplitude('01', autovector) + amp_after3 = eng.backend.get_amplitude('10', autovector) + amp_after4 = eng.backend.get_amplitude('11', autovector) + + print("Amplitude saved in amp_after1: {}".format(amp_after1)) + print("Amplitude saved in amp_after2: {}".format(amp_after2)) + print("Amplitude saved in amp_after3: {}".format(amp_after3)) + print("Amplitude saved in amp_after4: {}".format(amp_after4)) # Deferred measure del estado para que pueda imprimir cosas From 82613857e68cab20375ed80320f38fedadac3027 Mon Sep 17 00:00:00 2001 From: Fernando Date: Tue, 17 Jul 2018 17:24:38 +0200 Subject: [PATCH 05/29] Work in progress: create a PhaseX gate to tests via class --- examples/phase_estimation.py | 42 +++++- examples/settings.json | 89 ++++++++++++ examples/zoo.log | 43 ++++++ examples/zoo.tex | 260 +++++++++++++++++++++++++++++++++++ 4 files changed, 429 insertions(+), 5 deletions(-) create mode 100644 examples/settings.json create mode 100644 examples/zoo.log create mode 100644 examples/zoo.tex diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 35f17a02c..e86f5bfa0 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -3,6 +3,11 @@ from projectq.meta import Control from projectq import MainEngine +import cmath +import numpy as np +from projectq.ops import (BasicGate) +from projectq.types import BasicQubit + def phase_estimation(eng,unitary,eigenvector,n_ancillas): # create the ancillas and are left to |0> @@ -38,7 +43,21 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): print (fasebin, faseint,"fase final = ", fase) return fase - +class PhaseX(BasicGate): + """ + A phase gate on X gate with + eigenvectors H|0> and HX|0> and + eivenvalues exp(i2pi theta) and -exp(i2pi theta) + theta needs to be defined into the class by now + """ + @property + def matrix(self): + theta = 0.1234 + return np.matrix([[0,cmath.exp(1j * 2.0 * cmath.pi * theta)], + [cmath.exp(1j * 2.0 * cmath.pi * theta),0]]) + + def __str__(self): + return "PhaseX(theta)" if __name__ == "__main__": #Create the compiler engine @@ -48,11 +67,24 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): unitario = QubitOperator('X0 X1') #unitario = X - unit = TimeEvolution(1.0,unitario) + ### Example ###unit = TimeEvolution(1.0,unitario) + ### Example ###autovector = eng.allocate_qureg(2) + + ### Example ####unit = X + ### Example ####autovector = eng.allocate_qureg(1) + + #### Defined phase with X ### + + autovector = eng.allocate_qureg(1) + H | autovector + unit = PhaseX + print(type(unit)) + + #### END Defined phase with X ### - autovector = eng.allocate_qureg(2) - X | autovector[1] - All(H) | autovector + ### Example ###X | autovector[1] + ### Example ####X | autovector[0] + ### Example ###All(H) | autovector # Ask for the number of ancillas to use ene = int(input("How many ancillas?: ")) diff --git a/examples/settings.json b/examples/settings.json new file mode 100644 index 000000000..7b1396921 --- /dev/null +++ b/examples/settings.json @@ -0,0 +1,89 @@ +{ + "control": { + "shadow": false, + "size": 0.1 + }, + "gate_shadow": true, + "gates": { + "AllocateQubitGate": { + "allocate_at_zero": false, + "draw_id": false, + "height": 0.15, + "offset": 0.1, + "pre_offset": 0.1, + "width": 0.2 + }, + "DeallocateQubitGate": { + "height": 0.15, + "offset": 0.2, + "pre_offset": 0.1, + "width": 0.2 + }, + "EntangleGate": { + "offset": 0.2, + "pre_offset": 0.2, + "width": 1.8 + }, + "HGate": { + "offset": 0.3, + "pre_offset": 0.1, + "width": 0.5 + }, + "MeasureGate": { + "height": 0.5, + "offset": 0.2, + "pre_offset": 0.2, + "width": 0.75 + }, + "Ph": { + "height": 0.8, + "offset": 0.3, + "pre_offset": 0.2, + "width": 1.0 + }, + "Rx": { + "height": 0.8, + "offset": 0.3, + "pre_offset": 0.2, + "width": 1.0 + }, + "Ry": { + "height": 0.8, + "offset": 0.3, + "pre_offset": 0.2, + "width": 1.0 + }, + "Rz": { + "height": 0.8, + "offset": 0.3, + "pre_offset": 0.2, + "width": 1.0 + }, + "SqrtSwapGate": { + "height": 0.35, + "offset": 0.1, + "width": 0.35 + }, + "SqrtXGate": { + "offset": 0.3, + "pre_offset": 0.1, + "width": 0.7 + }, + "SwapGate": { + "height": 0.35, + "offset": 0.1, + "width": 0.35 + }, + "XGate": { + "height": 0.35, + "offset": 0.1, + "width": 0.35 + } + }, + "lines": { + "double_classical": true, + "double_lines_sep": 0.04, + "init_quantum": true, + "style": "very thin" + } +} \ No newline at end of file diff --git a/examples/zoo.log b/examples/zoo.log new file mode 100644 index 000000000..2c8d74f38 --- /dev/null +++ b/examples/zoo.log @@ -0,0 +1,43 @@ +This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013) (format=pdflatex 2018.6.13) 5 JUL 2018 13:12 +entering extended mode + restricted \write18 enabled. + %&-line parsing enabled. +**zoo.tex +(./zoo.tex +LaTeX2e <2011/06/27> +Babel and hyphenation patterns for english, dumylang, nohyphenation, lo +aded. + +! LaTeX Error: File `standalone.cls' not found. + +Type X to quit or to proceed, +or enter new name. (Default extension: cls) + +Enter file name: ajarenare + +! LaTeX Error: File `ajarenare.cls' not found. + +Type X to quit or to proceed, +or enter new name. (Default extension: cls) + +Enter file name: X + + ) +(\end occurred when \ifx on line 2 was incomplete) +(\end occurred when \ifx on line 2 was incomplete) +(\end occurred when \ifx on line 2 was incomplete) +Here is how much of TeX's memory you used: + 11 strings out of 495063 + 188 string characters out of 3182201 + 45057 words of memory out of 3000000 + 3291 multiletter control sequences out of 15000+200000 + 3640 words of font info for 14 fonts, out of 3000000 for 9000 + 14 hyphenation exceptions out of 8191 + 11i,0n,7p,63b,8s stack positions out of 5000i,500n,10000p,200000b,50000s + +No pages of output. +PDF statistics: + 0 PDF objects out of 1000 (max. 8388607) + 0 named destinations out of 1000 (max. 500000) + 1 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/examples/zoo.tex b/examples/zoo.tex new file mode 100644 index 000000000..86d8c164d --- /dev/null +++ b/examples/zoo.tex @@ -0,0 +1,260 @@ +\documentclass{standalone} +\usepackage[margin=1in]{geometry} +\usepackage[hang,small,bf]{caption} +\usepackage{tikz} +\usepackage{braket} +\usetikzlibrary{backgrounds,shadows.blur,fit,decorations.pathreplacing,shapes} + +\begin{document} +\begin{tikzpicture}[scale=0.8, transform shape] + +\tikzstyle{basicshadow}=[blur shadow={shadow blur steps=8, shadow xshift=0.7pt, shadow yshift=-0.7pt, shadow scale=1.02}]\tikzstyle{basic}=[draw,fill=white,basicshadow] +\tikzstyle{operator}=[basic,minimum size=1.5em] +\tikzstyle{phase}=[fill=black,shape=circle,minimum size=0.1cm,inner sep=0pt,outer sep=0pt,draw=black] +\tikzstyle{none}=[inner sep=0pt,outer sep=-.5pt,minimum height=0.5cm+1pt] +\tikzstyle{measure}=[operator,inner sep=0pt,minimum height=0.5cm, minimum width=0.75cm] +\tikzstyle{xstyle}=[circle,basic,minimum height=0.35cm,minimum width=0.35cm,inner sep=-1pt,very thin] +\tikzset{ +shadowed/.style={preaction={transform canvas={shift={(0.5pt,-0.5pt)}}, draw=gray, opacity=0.4}}, +} +\tikzstyle{swapstyle}=[inner sep=-1pt, outer sep=-1pt, minimum width=0pt] +\tikzstyle{edgestyle}=[very thin] + +\node[none] (line0_gate0) at (0.1,-0) {$\Ket{0}$}; +\node[none] (line0_gate1) at (0.6000000000000001,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate2) at (0.8500000000000001,-0) {}; +\node[none] (line0_gate3) at (1.1,-0) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate1) rectangle ([yshift=-0.25cm]line0_gate3) node[pos=.5] {Y}; +\draw (line0_gate0) edge[edgestyle] (line0_gate1); +\node[none] (line0_gate4) at (1.5,-0) {}; +\node[none,minimum height=0.8cm,outer sep=0] (line0_gate5) at (2.0,-0) {}; +\node[none] (line0_gate6) at (2.5,-0) {}; +\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line0_gate4) rectangle ([yshift=-0.4cm]line0_gate6) node[pos=.5] {Rx$_{0.5}$}; +\draw (line0_gate3) edge[edgestyle] (line0_gate4); +\node[none] (line0_gate7) at (3.0,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate8) at (3.25,-0) {}; +\node[none] (line0_gate9) at (3.5,-0) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate7) rectangle ([yshift=-0.25cm]line0_gate9) node[pos=.5] {T}; +\draw (line0_gate6) edge[edgestyle] (line0_gate7); +\node[none] (line1_gate0) at (0.1,-1) {$\Ket{0}$}; +\node[none] (line1_gate1) at (0.6000000000000001,-1) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line1_gate2) at (0.8500000000000001,-1) {}; +\node[none] (line1_gate3) at (1.1,-1) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line1_gate1) rectangle ([yshift=-0.25cm]line1_gate3) node[pos=.5] {Z}; +\draw (line1_gate0) edge[edgestyle] (line1_gate1); +\node[none] (line1_gate4) at (1.5,-1) {}; +\node[none,minimum height=0.8cm,outer sep=0] (line1_gate5) at (2.0,-1) {}; +\node[none] (line1_gate6) at (2.5,-1) {}; +\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line1_gate4) rectangle ([yshift=-0.4cm]line1_gate6) node[pos=.5] {Ph$_{0.5}$}; +\draw (line1_gate3) edge[edgestyle] (line1_gate4); +\node[none] (line2_gate0) at (0.1,-2) {$\Ket{0}$}; +\node[none] (line2_gate1) at (0.6000000000000001,-2) {}; +\node[none,minimum height=0.8cm,outer sep=0] (line2_gate2) at (1.1,-2) {}; +\node[none] (line2_gate3) at (1.6,-2) {}; +\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line2_gate1) rectangle ([yshift=-0.4cm]line2_gate3) node[pos=.5] {Ry$_{0.5}$}; +\draw (line2_gate0) edge[edgestyle] (line2_gate1); +\node[none] (line2_gate4) at (2.1,-2) {}; +\node[none,minimum height=0.8cm,outer sep=0] (line2_gate5) at (2.6,-2) {}; +\node[none] (line2_gate6) at (3.1,-2) {}; +\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line2_gate4) rectangle ([yshift=-0.4cm]line2_gate6) node[pos=.5] {Rz$_{0.5}$}; +\draw (line2_gate3) edge[edgestyle] (line2_gate4); +\node[none] (line2_gate7) at (3.5,-2) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line2_gate8) at (3.75,-2) {}; +\node[none] (line2_gate9) at (4.0,-2) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line2_gate7) rectangle ([yshift=-0.25cm]line2_gate9) node[pos=.5] {H}; +\draw (line2_gate6) edge[edgestyle] (line2_gate7); +\node[xstyle] (line0_gate10) at (4.3999999999999995,-0) {}; +\draw[edgestyle] (line0_gate10.north)--(line0_gate10.south); +\draw[edgestyle] (line0_gate10.west)--(line0_gate10.east); +\node[phase] (line1_gate7) at (4.3999999999999995,-1) {}; +\draw (line1_gate7) edge[edgestyle] (line0_gate10); +\node[phase] (line2_gate10) at (4.3999999999999995,-2) {}; +\draw (line2_gate10) edge[edgestyle] (line0_gate10); +\draw (line0_gate9) edge[edgestyle] (line0_gate10); +\draw (line1_gate6) edge[edgestyle] (line1_gate7); +\draw (line2_gate9) edge[edgestyle] (line2_gate10); +\node[none] (line3_gate0) at (0.1,-3) {$\Ket{0}$}; +\node[xstyle] (line3_gate1) at (0.5,-3) {}; +\draw[edgestyle] (line3_gate1.north)--(line3_gate1.south); +\draw[edgestyle] (line3_gate1.west)--(line3_gate1.east); +\draw (line3_gate0) edge[edgestyle] (line3_gate1); +\node[none] (line3_gate2) at (1.15,-3) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line3_gate3) at (1.4,-3) {}; +\node[none] (line3_gate4) at (1.65,-3) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line3_gate2) rectangle ([yshift=-0.25cm]line3_gate4) node[pos=.5] {S}; +\draw (line3_gate1) edge[edgestyle] (line3_gate2); +\node[none] (line0_gate11) at (5.049999999999999,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate12) at (5.299999999999999,-0) {}; +\node[none] (line0_gate13) at (5.549999999999999,-0) {}; +\node[none] (line1_gate8) at (5.049999999999999,-1) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line1_gate9) at (5.299999999999999,-1) {}; +\node[none] (line1_gate10) at (5.549999999999999,-1) {}; +\node[none] (line2_gate11) at (5.049999999999999,-2) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line2_gate12) at (5.299999999999999,-2) {}; +\node[none] (line2_gate13) at (5.549999999999999,-2) {}; +\node[none] (line3_gate5) at (5.049999999999999,-3) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line3_gate6) at (5.299999999999999,-3) {}; +\node[none] (line3_gate7) at (5.549999999999999,-3) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate11) rectangle ([yshift=-0.25cm]line3_gate7) node[pos=.5] {Barrier}; +\draw (line1_gate7) edge[edgestyle] (line1_gate8); +\draw (line2_gate10) edge[edgestyle] (line2_gate11); +\draw (line0_gate10) edge[edgestyle] (line0_gate11); +\draw (line3_gate4) edge[edgestyle] (line3_gate5); +\node[swapstyle] (line1_gate11) at (5.849999999999999,-1) {}; +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line1_gate11.center)--([xshift=0.175cm,yshift=0.175cm]line1_gate11.center); +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line1_gate11.center)--([xshift=0.175cm,yshift=-0.175cm]line1_gate11.center); +\node[swapstyle] (line3_gate8) at (5.849999999999999,-3) {}; +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line3_gate8.center)--([xshift=0.175cm,yshift=0.175cm]line3_gate8.center); +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line3_gate8.center)--([xshift=0.175cm,yshift=-0.175cm]line3_gate8.center); +\draw (line1_gate11) edge[edgestyle] (line3_gate8); +\draw (line1_gate10) edge[edgestyle] (line1_gate11); +\draw (line3_gate7) edge[edgestyle] (line3_gate8); +\node[swapstyle] (line0_gate14) at (6.399999999999998,-0) {}; +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line0_gate14.center)--([xshift=0.175cm,yshift=0.175cm]line0_gate14.center); +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line0_gate14.center)--([xshift=0.175cm,yshift=-0.175cm]line0_gate14.center); +\node[swapstyle] (line3_gate9) at (6.399999999999998,-3) {}; +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line3_gate9.center)--([xshift=0.175cm,yshift=0.175cm]line3_gate9.center); +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line3_gate9.center)--([xshift=0.175cm,yshift=-0.175cm]line3_gate9.center); +\node[xstyle] (line0-3_gate14) at (6.399999999999998,-1.5) {\scriptsize $\frac{1}{2}^{{\dagger}}$}; +\draw (line0_gate14) edge[edgestyle] (line0-3_gate14); +\draw (line0-3_gate14) edge[edgestyle] (line3_gate9); +\draw (line0_gate13) edge[edgestyle] (line0_gate14); +\draw (line3_gate8) edge[edgestyle] (line3_gate9); +\node[none] (line0_gate15) at (6.949999999999997,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate16) at (7.299999999999996,-0) {}; +\node[none] (line0_gate17) at (7.649999999999997,-0) {}; +\draw[operator,edgestyle,outer sep=0.7cm] ([yshift=0.25cm]line0_gate15) rectangle ([yshift=-0.25cm]line0_gate17) node[pos=.5] {$\sqrt{X}$}; +\draw (line0_gate14) edge[edgestyle] (line0_gate15); +\node[swapstyle] (line1_gate12) at (6.949999999999997,-1) {}; +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line1_gate12.center)--([xshift=0.175cm,yshift=0.175cm]line1_gate12.center); +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line1_gate12.center)--([xshift=0.175cm,yshift=-0.175cm]line1_gate12.center); +\node[swapstyle] (line2_gate14) at (6.949999999999997,-2) {}; +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line2_gate14.center)--([xshift=0.175cm,yshift=0.175cm]line2_gate14.center); +\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line2_gate14.center)--([xshift=0.175cm,yshift=-0.175cm]line2_gate14.center); +\node[xstyle] (line1-2_gate12) at (6.949999999999997,-1.5) {\scriptsize $\frac{1}{2}$}; +\draw (line1_gate12) edge[edgestyle] (line1-2_gate12); +\draw (line1-2_gate12) edge[edgestyle] (line2_gate14); +\draw (line1_gate11) edge[edgestyle] (line1_gate12); +\draw (line2_gate13) edge[edgestyle] (line2_gate14); +\node[none] (line0_gate18) at (8.049999999999997,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate19) at (8.399999999999997,-0) {}; +\node[none] (line0_gate20) at (8.749999999999996,-0) {}; +\draw[operator,edgestyle,outer sep=0.7cm] ([yshift=0.25cm]line0_gate18) rectangle ([yshift=-0.25cm]line0_gate20) node[pos=.5] {$\sqrt{X}$${}^\dagger$}; +\node[phase] (line1_gate13) at (8.399999999999997,-1) {}; +\draw (line1_gate13) edge[edgestyle] (line0_gate19); +\draw (line0_gate17) edge[edgestyle] (line0_gate18); +\draw (line1_gate12) edge[edgestyle] (line1_gate13); +\node[none] (line3_gate10) at (9.249999999999996,-3) {}; +\node[none,minimum height=0.8cm,outer sep=0] (line3_gate11) at (9.749999999999996,-3) {}; +\node[none] (line3_gate12) at (10.249999999999996,-3) {}; +\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line3_gate10) rectangle ([yshift=-0.4cm]line3_gate12) node[pos=.5] {Ry$_{0.5}$}; +\node[phase] (line0_gate21) at (9.749999999999996,-0) {}; +\draw (line0_gate21) edge[edgestyle] (line3_gate11); +\draw (line3_gate9) edge[edgestyle] (line3_gate10); +\draw (line0_gate20) edge[edgestyle] (line0_gate21); +\node[xstyle] (line2_gate15) at (10.649999999999997,-2) {}; +\draw[edgestyle] (line2_gate15.north)--(line2_gate15.south); +\draw[edgestyle] (line2_gate15.west)--(line2_gate15.east); +\node[phase] (line0_gate22) at (10.649999999999997,-0) {}; +\draw (line0_gate22) edge[edgestyle] (line2_gate15); +\draw (line2_gate14) edge[edgestyle] (line2_gate15); +\draw (line0_gate21) edge[edgestyle] (line0_gate22); +\node[none] (line0_gate23) at (11.299999999999995,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate24) at (12.199999999999996,-0) {}; +\node[none] (line0_gate25) at (13.099999999999996,-0) {}; +\node[none] (line1_gate14) at (11.299999999999995,-1) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line1_gate15) at (12.199999999999996,-1) {}; +\node[none] (line1_gate16) at (13.099999999999996,-1) {}; +\node[none] (line2_gate16) at (11.299999999999995,-2) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line2_gate17) at (12.199999999999996,-2) {}; +\node[none] (line2_gate18) at (13.099999999999996,-2) {}; +\node[none] (line3_gate13) at (11.299999999999995,-3) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line3_gate14) at (12.199999999999996,-3) {}; +\node[none] (line3_gate15) at (13.099999999999996,-3) {}; +\draw[operator,edgestyle,outer sep=1.8cm] ([yshift=0.25cm]line0_gate23) rectangle ([yshift=-0.25cm]line3_gate15) node[pos=.5] {Entangle}; +\draw (line1_gate13) edge[edgestyle] (line1_gate14); +\draw (line2_gate15) edge[edgestyle] (line2_gate16); +\draw (line0_gate22) edge[edgestyle] (line0_gate23); +\draw (line3_gate12) edge[edgestyle] (line3_gate13); +\node[none] (line0_gate26) at (13.499999999999995,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate27) at (13.749999999999995,-0) {}; +\node[none] (line0_gate28) at (13.999999999999995,-0) {}; +\node[none] (line1_gate17) at (13.499999999999995,-1) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line1_gate18) at (13.749999999999995,-1) {}; +\node[none] (line1_gate19) at (13.999999999999995,-1) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate26) rectangle ([yshift=-0.25cm]line1_gate19) node[pos=.5] {exp(-0.5j * (0.1 X0 Y1))}; +\draw (line1_gate16) edge[edgestyle] (line1_gate17); +\draw (line0_gate25) edge[edgestyle] (line0_gate26); +\node[none] (line0_gate29) at (14.399999999999993,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate30) at (14.649999999999993,-0) {}; +\node[none] (line0_gate31) at (14.899999999999993,-0) {}; +\node[none] (line1_gate20) at (14.399999999999993,-1) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line1_gate21) at (14.649999999999993,-1) {}; +\node[none] (line1_gate22) at (14.899999999999993,-1) {}; +\node[none] (line2_gate19) at (14.399999999999993,-2) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line2_gate20) at (14.649999999999993,-2) {}; +\node[none] (line2_gate21) at (14.899999999999993,-2) {}; +\node[none] (line3_gate16) at (14.399999999999993,-3) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line3_gate17) at (14.649999999999993,-3) {}; +\node[none] (line3_gate18) at (14.899999999999993,-3) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate29) rectangle ([yshift=-0.25cm]line3_gate18) node[pos=.5] {QFT}; +\draw (line1_gate19) edge[edgestyle] (line1_gate20); +\draw (line2_gate18) edge[edgestyle] (line2_gate19); +\draw (line0_gate28) edge[edgestyle] (line0_gate29); +\draw (line3_gate15) edge[edgestyle] (line3_gate16); +\node[none] (line0_gate32) at (15.199999999999992,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate33) at (15.449999999999992,-0) {}; +\node[none] (line0_gate34) at (15.699999999999992,-0) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate32) rectangle ([yshift=-0.25cm]line0_gate34) node[pos=.5] {H}; +\draw (line0_gate31) edge[edgestyle] (line0_gate32); +\node[none] (line3_gate19) at (15.199999999999992,-3) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line3_gate20) at (15.449999999999992,-3) {}; +\node[none] (line3_gate21) at (15.699999999999992,-3) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line3_gate19) rectangle ([yshift=-0.25cm]line3_gate21) node[pos=.5] {H}; +\draw (line3_gate18) edge[edgestyle] (line3_gate19); +\node[none] (line0_gate35) at (16.199999999999992,-0) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line0_gate36) at (16.449999999999992,-0) {}; +\node[none] (line0_gate37) at (16.699999999999992,-0) {}; +\node[none] (line1_gate23) at (16.199999999999992,-1) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line1_gate24) at (16.449999999999992,-1) {}; +\node[none] (line1_gate25) at (16.699999999999992,-1) {}; +\draw (line1_gate22) edge[edgestyle] (line1_gate23); +\node[none] (line2_gate22) at (16.199999999999992,-2) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line2_gate23) at (16.449999999999992,-2) {}; +\node[none] (line2_gate24) at (16.699999999999992,-2) {}; +\draw (line2_gate21) edge[edgestyle] (line2_gate22); +\node[none] (line3_gate22) at (16.199999999999992,-3) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line3_gate23) at (16.449999999999992,-3) {}; +\node[none] (line3_gate24) at (16.699999999999992,-3) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate35) rectangle ([yshift=-0.25cm]line3_gate24) node[pos=.5] {MATH}; +\draw (line0_gate34) edge[edgestyle] (line0_gate35); +\draw (line3_gate21) edge[edgestyle] (line3_gate22); +\node[measure,edgestyle] (line0_gate38) at (17.09999999999999,-0) {}; +\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line0_gate38.west) to [out=60,in=180] ([yshift=0.035cm]line0_gate38.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line0_gate38.east); +\draw[edgestyle] ([yshift=-0.18cm]line0_gate38.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line0_gate38.north east); +\draw (line0_gate37) edge[edgestyle] (line0_gate38); +\node[none] (line1_gate26) at (16.999999999999993,-1) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line1_gate27) at (17.249999999999993,-1) {}; +\node[none] (line1_gate28) at (17.499999999999993,-1) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line1_gate26) rectangle ([yshift=-0.25cm]line1_gate28) node[pos=.5] {H}; +\draw (line1_gate25) edge[edgestyle] (line1_gate26); +\node[measure,edgestyle] (line1_gate29) at (17.999999999999993,-1) {}; +\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line1_gate29.west) to [out=60,in=180] ([yshift=0.035cm]line1_gate29.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line1_gate29.east); +\draw[edgestyle] ([yshift=-0.18cm]line1_gate29.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line1_gate29.north east); +\draw (line1_gate28) edge[edgestyle] (line1_gate29); +\node[none] (line2_gate25) at (16.999999999999993,-2) {}; +\node[none,minimum height=0.5cm,outer sep=0] (line2_gate26) at (17.249999999999993,-2) {}; +\node[none] (line2_gate27) at (17.499999999999993,-2) {}; +\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line2_gate25) rectangle ([yshift=-0.25cm]line2_gate27) node[pos=.5] {H}; +\draw (line2_gate24) edge[edgestyle] (line2_gate25); +\node[measure,edgestyle] (line2_gate28) at (17.999999999999993,-2) {}; +\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line2_gate28.west) to [out=60,in=180] ([yshift=0.035cm]line2_gate28.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line2_gate28.east); +\draw[edgestyle] ([yshift=-0.18cm]line2_gate28.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line2_gate28.north east); +\draw (line2_gate27) edge[edgestyle] (line2_gate28); +\node[measure,edgestyle] (line3_gate25) at (17.09999999999999,-3) {}; +\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line3_gate25.west) to [out=60,in=180] ([yshift=0.035cm]line3_gate25.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line3_gate25.east); +\draw[edgestyle] ([yshift=-0.18cm]line3_gate25.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line3_gate25.north east); +\draw (line3_gate24) edge[edgestyle] (line3_gate25); + +\end{tikzpicture} +\end{document} \ No newline at end of file From 630247d78466757b79f5e201172a5346d6b9d101 Mon Sep 17 00:00:00 2001 From: Fernando Date: Tue, 17 Jul 2018 17:31:12 +0200 Subject: [PATCH 06/29] Work in progress: create a PhaseX gate to tests via class. Clean garbaje files --- examples/settings.json | 89 -------------- examples/zoo.log | 43 ------- examples/zoo.tex | 260 ----------------------------------------- 3 files changed, 392 deletions(-) delete mode 100644 examples/settings.json delete mode 100644 examples/zoo.log delete mode 100644 examples/zoo.tex diff --git a/examples/settings.json b/examples/settings.json deleted file mode 100644 index 7b1396921..000000000 --- a/examples/settings.json +++ /dev/null @@ -1,89 +0,0 @@ -{ - "control": { - "shadow": false, - "size": 0.1 - }, - "gate_shadow": true, - "gates": { - "AllocateQubitGate": { - "allocate_at_zero": false, - "draw_id": false, - "height": 0.15, - "offset": 0.1, - "pre_offset": 0.1, - "width": 0.2 - }, - "DeallocateQubitGate": { - "height": 0.15, - "offset": 0.2, - "pre_offset": 0.1, - "width": 0.2 - }, - "EntangleGate": { - "offset": 0.2, - "pre_offset": 0.2, - "width": 1.8 - }, - "HGate": { - "offset": 0.3, - "pre_offset": 0.1, - "width": 0.5 - }, - "MeasureGate": { - "height": 0.5, - "offset": 0.2, - "pre_offset": 0.2, - "width": 0.75 - }, - "Ph": { - "height": 0.8, - "offset": 0.3, - "pre_offset": 0.2, - "width": 1.0 - }, - "Rx": { - "height": 0.8, - "offset": 0.3, - "pre_offset": 0.2, - "width": 1.0 - }, - "Ry": { - "height": 0.8, - "offset": 0.3, - "pre_offset": 0.2, - "width": 1.0 - }, - "Rz": { - "height": 0.8, - "offset": 0.3, - "pre_offset": 0.2, - "width": 1.0 - }, - "SqrtSwapGate": { - "height": 0.35, - "offset": 0.1, - "width": 0.35 - }, - "SqrtXGate": { - "offset": 0.3, - "pre_offset": 0.1, - "width": 0.7 - }, - "SwapGate": { - "height": 0.35, - "offset": 0.1, - "width": 0.35 - }, - "XGate": { - "height": 0.35, - "offset": 0.1, - "width": 0.35 - } - }, - "lines": { - "double_classical": true, - "double_lines_sep": 0.04, - "init_quantum": true, - "style": "very thin" - } -} \ No newline at end of file diff --git a/examples/zoo.log b/examples/zoo.log deleted file mode 100644 index 2c8d74f38..000000000 --- a/examples/zoo.log +++ /dev/null @@ -1,43 +0,0 @@ -This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013) (format=pdflatex 2018.6.13) 5 JUL 2018 13:12 -entering extended mode - restricted \write18 enabled. - %&-line parsing enabled. -**zoo.tex -(./zoo.tex -LaTeX2e <2011/06/27> -Babel and hyphenation patterns for english, dumylang, nohyphenation, lo -aded. - -! LaTeX Error: File `standalone.cls' not found. - -Type X to quit or to proceed, -or enter new name. (Default extension: cls) - -Enter file name: ajarenare - -! LaTeX Error: File `ajarenare.cls' not found. - -Type X to quit or to proceed, -or enter new name. (Default extension: cls) - -Enter file name: X - - ) -(\end occurred when \ifx on line 2 was incomplete) -(\end occurred when \ifx on line 2 was incomplete) -(\end occurred when \ifx on line 2 was incomplete) -Here is how much of TeX's memory you used: - 11 strings out of 495063 - 188 string characters out of 3182201 - 45057 words of memory out of 3000000 - 3291 multiletter control sequences out of 15000+200000 - 3640 words of font info for 14 fonts, out of 3000000 for 9000 - 14 hyphenation exceptions out of 8191 - 11i,0n,7p,63b,8s stack positions out of 5000i,500n,10000p,200000b,50000s - -No pages of output. -PDF statistics: - 0 PDF objects out of 1000 (max. 8388607) - 0 named destinations out of 1000 (max. 500000) - 1 words of extra memory for PDF output out of 10000 (max. 10000000) - diff --git a/examples/zoo.tex b/examples/zoo.tex deleted file mode 100644 index 86d8c164d..000000000 --- a/examples/zoo.tex +++ /dev/null @@ -1,260 +0,0 @@ -\documentclass{standalone} -\usepackage[margin=1in]{geometry} -\usepackage[hang,small,bf]{caption} -\usepackage{tikz} -\usepackage{braket} -\usetikzlibrary{backgrounds,shadows.blur,fit,decorations.pathreplacing,shapes} - -\begin{document} -\begin{tikzpicture}[scale=0.8, transform shape] - -\tikzstyle{basicshadow}=[blur shadow={shadow blur steps=8, shadow xshift=0.7pt, shadow yshift=-0.7pt, shadow scale=1.02}]\tikzstyle{basic}=[draw,fill=white,basicshadow] -\tikzstyle{operator}=[basic,minimum size=1.5em] -\tikzstyle{phase}=[fill=black,shape=circle,minimum size=0.1cm,inner sep=0pt,outer sep=0pt,draw=black] -\tikzstyle{none}=[inner sep=0pt,outer sep=-.5pt,minimum height=0.5cm+1pt] -\tikzstyle{measure}=[operator,inner sep=0pt,minimum height=0.5cm, minimum width=0.75cm] -\tikzstyle{xstyle}=[circle,basic,minimum height=0.35cm,minimum width=0.35cm,inner sep=-1pt,very thin] -\tikzset{ -shadowed/.style={preaction={transform canvas={shift={(0.5pt,-0.5pt)}}, draw=gray, opacity=0.4}}, -} -\tikzstyle{swapstyle}=[inner sep=-1pt, outer sep=-1pt, minimum width=0pt] -\tikzstyle{edgestyle}=[very thin] - -\node[none] (line0_gate0) at (0.1,-0) {$\Ket{0}$}; -\node[none] (line0_gate1) at (0.6000000000000001,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate2) at (0.8500000000000001,-0) {}; -\node[none] (line0_gate3) at (1.1,-0) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate1) rectangle ([yshift=-0.25cm]line0_gate3) node[pos=.5] {Y}; -\draw (line0_gate0) edge[edgestyle] (line0_gate1); -\node[none] (line0_gate4) at (1.5,-0) {}; -\node[none,minimum height=0.8cm,outer sep=0] (line0_gate5) at (2.0,-0) {}; -\node[none] (line0_gate6) at (2.5,-0) {}; -\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line0_gate4) rectangle ([yshift=-0.4cm]line0_gate6) node[pos=.5] {Rx$_{0.5}$}; -\draw (line0_gate3) edge[edgestyle] (line0_gate4); -\node[none] (line0_gate7) at (3.0,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate8) at (3.25,-0) {}; -\node[none] (line0_gate9) at (3.5,-0) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate7) rectangle ([yshift=-0.25cm]line0_gate9) node[pos=.5] {T}; -\draw (line0_gate6) edge[edgestyle] (line0_gate7); -\node[none] (line1_gate0) at (0.1,-1) {$\Ket{0}$}; -\node[none] (line1_gate1) at (0.6000000000000001,-1) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line1_gate2) at (0.8500000000000001,-1) {}; -\node[none] (line1_gate3) at (1.1,-1) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line1_gate1) rectangle ([yshift=-0.25cm]line1_gate3) node[pos=.5] {Z}; -\draw (line1_gate0) edge[edgestyle] (line1_gate1); -\node[none] (line1_gate4) at (1.5,-1) {}; -\node[none,minimum height=0.8cm,outer sep=0] (line1_gate5) at (2.0,-1) {}; -\node[none] (line1_gate6) at (2.5,-1) {}; -\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line1_gate4) rectangle ([yshift=-0.4cm]line1_gate6) node[pos=.5] {Ph$_{0.5}$}; -\draw (line1_gate3) edge[edgestyle] (line1_gate4); -\node[none] (line2_gate0) at (0.1,-2) {$\Ket{0}$}; -\node[none] (line2_gate1) at (0.6000000000000001,-2) {}; -\node[none,minimum height=0.8cm,outer sep=0] (line2_gate2) at (1.1,-2) {}; -\node[none] (line2_gate3) at (1.6,-2) {}; -\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line2_gate1) rectangle ([yshift=-0.4cm]line2_gate3) node[pos=.5] {Ry$_{0.5}$}; -\draw (line2_gate0) edge[edgestyle] (line2_gate1); -\node[none] (line2_gate4) at (2.1,-2) {}; -\node[none,minimum height=0.8cm,outer sep=0] (line2_gate5) at (2.6,-2) {}; -\node[none] (line2_gate6) at (3.1,-2) {}; -\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line2_gate4) rectangle ([yshift=-0.4cm]line2_gate6) node[pos=.5] {Rz$_{0.5}$}; -\draw (line2_gate3) edge[edgestyle] (line2_gate4); -\node[none] (line2_gate7) at (3.5,-2) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line2_gate8) at (3.75,-2) {}; -\node[none] (line2_gate9) at (4.0,-2) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line2_gate7) rectangle ([yshift=-0.25cm]line2_gate9) node[pos=.5] {H}; -\draw (line2_gate6) edge[edgestyle] (line2_gate7); -\node[xstyle] (line0_gate10) at (4.3999999999999995,-0) {}; -\draw[edgestyle] (line0_gate10.north)--(line0_gate10.south); -\draw[edgestyle] (line0_gate10.west)--(line0_gate10.east); -\node[phase] (line1_gate7) at (4.3999999999999995,-1) {}; -\draw (line1_gate7) edge[edgestyle] (line0_gate10); -\node[phase] (line2_gate10) at (4.3999999999999995,-2) {}; -\draw (line2_gate10) edge[edgestyle] (line0_gate10); -\draw (line0_gate9) edge[edgestyle] (line0_gate10); -\draw (line1_gate6) edge[edgestyle] (line1_gate7); -\draw (line2_gate9) edge[edgestyle] (line2_gate10); -\node[none] (line3_gate0) at (0.1,-3) {$\Ket{0}$}; -\node[xstyle] (line3_gate1) at (0.5,-3) {}; -\draw[edgestyle] (line3_gate1.north)--(line3_gate1.south); -\draw[edgestyle] (line3_gate1.west)--(line3_gate1.east); -\draw (line3_gate0) edge[edgestyle] (line3_gate1); -\node[none] (line3_gate2) at (1.15,-3) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line3_gate3) at (1.4,-3) {}; -\node[none] (line3_gate4) at (1.65,-3) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line3_gate2) rectangle ([yshift=-0.25cm]line3_gate4) node[pos=.5] {S}; -\draw (line3_gate1) edge[edgestyle] (line3_gate2); -\node[none] (line0_gate11) at (5.049999999999999,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate12) at (5.299999999999999,-0) {}; -\node[none] (line0_gate13) at (5.549999999999999,-0) {}; -\node[none] (line1_gate8) at (5.049999999999999,-1) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line1_gate9) at (5.299999999999999,-1) {}; -\node[none] (line1_gate10) at (5.549999999999999,-1) {}; -\node[none] (line2_gate11) at (5.049999999999999,-2) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line2_gate12) at (5.299999999999999,-2) {}; -\node[none] (line2_gate13) at (5.549999999999999,-2) {}; -\node[none] (line3_gate5) at (5.049999999999999,-3) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line3_gate6) at (5.299999999999999,-3) {}; -\node[none] (line3_gate7) at (5.549999999999999,-3) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate11) rectangle ([yshift=-0.25cm]line3_gate7) node[pos=.5] {Barrier}; -\draw (line1_gate7) edge[edgestyle] (line1_gate8); -\draw (line2_gate10) edge[edgestyle] (line2_gate11); -\draw (line0_gate10) edge[edgestyle] (line0_gate11); -\draw (line3_gate4) edge[edgestyle] (line3_gate5); -\node[swapstyle] (line1_gate11) at (5.849999999999999,-1) {}; -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line1_gate11.center)--([xshift=0.175cm,yshift=0.175cm]line1_gate11.center); -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line1_gate11.center)--([xshift=0.175cm,yshift=-0.175cm]line1_gate11.center); -\node[swapstyle] (line3_gate8) at (5.849999999999999,-3) {}; -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line3_gate8.center)--([xshift=0.175cm,yshift=0.175cm]line3_gate8.center); -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line3_gate8.center)--([xshift=0.175cm,yshift=-0.175cm]line3_gate8.center); -\draw (line1_gate11) edge[edgestyle] (line3_gate8); -\draw (line1_gate10) edge[edgestyle] (line1_gate11); -\draw (line3_gate7) edge[edgestyle] (line3_gate8); -\node[swapstyle] (line0_gate14) at (6.399999999999998,-0) {}; -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line0_gate14.center)--([xshift=0.175cm,yshift=0.175cm]line0_gate14.center); -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line0_gate14.center)--([xshift=0.175cm,yshift=-0.175cm]line0_gate14.center); -\node[swapstyle] (line3_gate9) at (6.399999999999998,-3) {}; -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line3_gate9.center)--([xshift=0.175cm,yshift=0.175cm]line3_gate9.center); -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line3_gate9.center)--([xshift=0.175cm,yshift=-0.175cm]line3_gate9.center); -\node[xstyle] (line0-3_gate14) at (6.399999999999998,-1.5) {\scriptsize $\frac{1}{2}^{{\dagger}}$}; -\draw (line0_gate14) edge[edgestyle] (line0-3_gate14); -\draw (line0-3_gate14) edge[edgestyle] (line3_gate9); -\draw (line0_gate13) edge[edgestyle] (line0_gate14); -\draw (line3_gate8) edge[edgestyle] (line3_gate9); -\node[none] (line0_gate15) at (6.949999999999997,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate16) at (7.299999999999996,-0) {}; -\node[none] (line0_gate17) at (7.649999999999997,-0) {}; -\draw[operator,edgestyle,outer sep=0.7cm] ([yshift=0.25cm]line0_gate15) rectangle ([yshift=-0.25cm]line0_gate17) node[pos=.5] {$\sqrt{X}$}; -\draw (line0_gate14) edge[edgestyle] (line0_gate15); -\node[swapstyle] (line1_gate12) at (6.949999999999997,-1) {}; -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line1_gate12.center)--([xshift=0.175cm,yshift=0.175cm]line1_gate12.center); -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line1_gate12.center)--([xshift=0.175cm,yshift=-0.175cm]line1_gate12.center); -\node[swapstyle] (line2_gate14) at (6.949999999999997,-2) {}; -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=-0.175cm]line2_gate14.center)--([xshift=0.175cm,yshift=0.175cm]line2_gate14.center); -\draw[swapstyle,edgestyle,shadowed] ([xshift=-0.175cm,yshift=0.175cm]line2_gate14.center)--([xshift=0.175cm,yshift=-0.175cm]line2_gate14.center); -\node[xstyle] (line1-2_gate12) at (6.949999999999997,-1.5) {\scriptsize $\frac{1}{2}$}; -\draw (line1_gate12) edge[edgestyle] (line1-2_gate12); -\draw (line1-2_gate12) edge[edgestyle] (line2_gate14); -\draw (line1_gate11) edge[edgestyle] (line1_gate12); -\draw (line2_gate13) edge[edgestyle] (line2_gate14); -\node[none] (line0_gate18) at (8.049999999999997,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate19) at (8.399999999999997,-0) {}; -\node[none] (line0_gate20) at (8.749999999999996,-0) {}; -\draw[operator,edgestyle,outer sep=0.7cm] ([yshift=0.25cm]line0_gate18) rectangle ([yshift=-0.25cm]line0_gate20) node[pos=.5] {$\sqrt{X}$${}^\dagger$}; -\node[phase] (line1_gate13) at (8.399999999999997,-1) {}; -\draw (line1_gate13) edge[edgestyle] (line0_gate19); -\draw (line0_gate17) edge[edgestyle] (line0_gate18); -\draw (line1_gate12) edge[edgestyle] (line1_gate13); -\node[none] (line3_gate10) at (9.249999999999996,-3) {}; -\node[none,minimum height=0.8cm,outer sep=0] (line3_gate11) at (9.749999999999996,-3) {}; -\node[none] (line3_gate12) at (10.249999999999996,-3) {}; -\draw[operator,edgestyle,outer sep=1.0cm] ([yshift=0.4cm]line3_gate10) rectangle ([yshift=-0.4cm]line3_gate12) node[pos=.5] {Ry$_{0.5}$}; -\node[phase] (line0_gate21) at (9.749999999999996,-0) {}; -\draw (line0_gate21) edge[edgestyle] (line3_gate11); -\draw (line3_gate9) edge[edgestyle] (line3_gate10); -\draw (line0_gate20) edge[edgestyle] (line0_gate21); -\node[xstyle] (line2_gate15) at (10.649999999999997,-2) {}; -\draw[edgestyle] (line2_gate15.north)--(line2_gate15.south); -\draw[edgestyle] (line2_gate15.west)--(line2_gate15.east); -\node[phase] (line0_gate22) at (10.649999999999997,-0) {}; -\draw (line0_gate22) edge[edgestyle] (line2_gate15); -\draw (line2_gate14) edge[edgestyle] (line2_gate15); -\draw (line0_gate21) edge[edgestyle] (line0_gate22); -\node[none] (line0_gate23) at (11.299999999999995,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate24) at (12.199999999999996,-0) {}; -\node[none] (line0_gate25) at (13.099999999999996,-0) {}; -\node[none] (line1_gate14) at (11.299999999999995,-1) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line1_gate15) at (12.199999999999996,-1) {}; -\node[none] (line1_gate16) at (13.099999999999996,-1) {}; -\node[none] (line2_gate16) at (11.299999999999995,-2) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line2_gate17) at (12.199999999999996,-2) {}; -\node[none] (line2_gate18) at (13.099999999999996,-2) {}; -\node[none] (line3_gate13) at (11.299999999999995,-3) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line3_gate14) at (12.199999999999996,-3) {}; -\node[none] (line3_gate15) at (13.099999999999996,-3) {}; -\draw[operator,edgestyle,outer sep=1.8cm] ([yshift=0.25cm]line0_gate23) rectangle ([yshift=-0.25cm]line3_gate15) node[pos=.5] {Entangle}; -\draw (line1_gate13) edge[edgestyle] (line1_gate14); -\draw (line2_gate15) edge[edgestyle] (line2_gate16); -\draw (line0_gate22) edge[edgestyle] (line0_gate23); -\draw (line3_gate12) edge[edgestyle] (line3_gate13); -\node[none] (line0_gate26) at (13.499999999999995,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate27) at (13.749999999999995,-0) {}; -\node[none] (line0_gate28) at (13.999999999999995,-0) {}; -\node[none] (line1_gate17) at (13.499999999999995,-1) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line1_gate18) at (13.749999999999995,-1) {}; -\node[none] (line1_gate19) at (13.999999999999995,-1) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate26) rectangle ([yshift=-0.25cm]line1_gate19) node[pos=.5] {exp(-0.5j * (0.1 X0 Y1))}; -\draw (line1_gate16) edge[edgestyle] (line1_gate17); -\draw (line0_gate25) edge[edgestyle] (line0_gate26); -\node[none] (line0_gate29) at (14.399999999999993,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate30) at (14.649999999999993,-0) {}; -\node[none] (line0_gate31) at (14.899999999999993,-0) {}; -\node[none] (line1_gate20) at (14.399999999999993,-1) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line1_gate21) at (14.649999999999993,-1) {}; -\node[none] (line1_gate22) at (14.899999999999993,-1) {}; -\node[none] (line2_gate19) at (14.399999999999993,-2) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line2_gate20) at (14.649999999999993,-2) {}; -\node[none] (line2_gate21) at (14.899999999999993,-2) {}; -\node[none] (line3_gate16) at (14.399999999999993,-3) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line3_gate17) at (14.649999999999993,-3) {}; -\node[none] (line3_gate18) at (14.899999999999993,-3) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate29) rectangle ([yshift=-0.25cm]line3_gate18) node[pos=.5] {QFT}; -\draw (line1_gate19) edge[edgestyle] (line1_gate20); -\draw (line2_gate18) edge[edgestyle] (line2_gate19); -\draw (line0_gate28) edge[edgestyle] (line0_gate29); -\draw (line3_gate15) edge[edgestyle] (line3_gate16); -\node[none] (line0_gate32) at (15.199999999999992,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate33) at (15.449999999999992,-0) {}; -\node[none] (line0_gate34) at (15.699999999999992,-0) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate32) rectangle ([yshift=-0.25cm]line0_gate34) node[pos=.5] {H}; -\draw (line0_gate31) edge[edgestyle] (line0_gate32); -\node[none] (line3_gate19) at (15.199999999999992,-3) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line3_gate20) at (15.449999999999992,-3) {}; -\node[none] (line3_gate21) at (15.699999999999992,-3) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line3_gate19) rectangle ([yshift=-0.25cm]line3_gate21) node[pos=.5] {H}; -\draw (line3_gate18) edge[edgestyle] (line3_gate19); -\node[none] (line0_gate35) at (16.199999999999992,-0) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line0_gate36) at (16.449999999999992,-0) {}; -\node[none] (line0_gate37) at (16.699999999999992,-0) {}; -\node[none] (line1_gate23) at (16.199999999999992,-1) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line1_gate24) at (16.449999999999992,-1) {}; -\node[none] (line1_gate25) at (16.699999999999992,-1) {}; -\draw (line1_gate22) edge[edgestyle] (line1_gate23); -\node[none] (line2_gate22) at (16.199999999999992,-2) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line2_gate23) at (16.449999999999992,-2) {}; -\node[none] (line2_gate24) at (16.699999999999992,-2) {}; -\draw (line2_gate21) edge[edgestyle] (line2_gate22); -\node[none] (line3_gate22) at (16.199999999999992,-3) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line3_gate23) at (16.449999999999992,-3) {}; -\node[none] (line3_gate24) at (16.699999999999992,-3) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line0_gate35) rectangle ([yshift=-0.25cm]line3_gate24) node[pos=.5] {MATH}; -\draw (line0_gate34) edge[edgestyle] (line0_gate35); -\draw (line3_gate21) edge[edgestyle] (line3_gate22); -\node[measure,edgestyle] (line0_gate38) at (17.09999999999999,-0) {}; -\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line0_gate38.west) to [out=60,in=180] ([yshift=0.035cm]line0_gate38.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line0_gate38.east); -\draw[edgestyle] ([yshift=-0.18cm]line0_gate38.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line0_gate38.north east); -\draw (line0_gate37) edge[edgestyle] (line0_gate38); -\node[none] (line1_gate26) at (16.999999999999993,-1) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line1_gate27) at (17.249999999999993,-1) {}; -\node[none] (line1_gate28) at (17.499999999999993,-1) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line1_gate26) rectangle ([yshift=-0.25cm]line1_gate28) node[pos=.5] {H}; -\draw (line1_gate25) edge[edgestyle] (line1_gate26); -\node[measure,edgestyle] (line1_gate29) at (17.999999999999993,-1) {}; -\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line1_gate29.west) to [out=60,in=180] ([yshift=0.035cm]line1_gate29.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line1_gate29.east); -\draw[edgestyle] ([yshift=-0.18cm]line1_gate29.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line1_gate29.north east); -\draw (line1_gate28) edge[edgestyle] (line1_gate29); -\node[none] (line2_gate25) at (16.999999999999993,-2) {}; -\node[none,minimum height=0.5cm,outer sep=0] (line2_gate26) at (17.249999999999993,-2) {}; -\node[none] (line2_gate27) at (17.499999999999993,-2) {}; -\draw[operator,edgestyle,outer sep=0.5cm] ([yshift=0.25cm]line2_gate25) rectangle ([yshift=-0.25cm]line2_gate27) node[pos=.5] {H}; -\draw (line2_gate24) edge[edgestyle] (line2_gate25); -\node[measure,edgestyle] (line2_gate28) at (17.999999999999993,-2) {}; -\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line2_gate28.west) to [out=60,in=180] ([yshift=0.035cm]line2_gate28.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line2_gate28.east); -\draw[edgestyle] ([yshift=-0.18cm]line2_gate28.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line2_gate28.north east); -\draw (line2_gate27) edge[edgestyle] (line2_gate28); -\node[measure,edgestyle] (line3_gate25) at (17.09999999999999,-3) {}; -\draw[edgestyle] ([yshift=-0.18cm,xshift=0.07500000000000001cm]line3_gate25.west) to [out=60,in=180] ([yshift=0.035cm]line3_gate25.center) to [out=0, in=120] ([yshift=-0.18cm,xshift=-0.07500000000000001cm]line3_gate25.east); -\draw[edgestyle] ([yshift=-0.18cm]line3_gate25.center) to ([yshift=-0.07500000000000001cm,xshift=-0.18cm]line3_gate25.north east); -\draw (line3_gate24) edge[edgestyle] (line3_gate25); - -\end{tikzpicture} -\end{document} \ No newline at end of file From d512a24f00cebd9e3fb22671ce9e725951acb957 Mon Sep 17 00:00:00 2001 From: Fernando Date: Wed, 18 Jul 2018 21:03:57 +0200 Subject: [PATCH 07/29] Work in progress: create a PhaseX gate to tests via class. Some enhanement --- examples/phase_estimation.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index e86f5bfa0..03785886f 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -50,9 +50,17 @@ class PhaseX(BasicGate): eivenvalues exp(i2pi theta) and -exp(i2pi theta) theta needs to be defined into the class by now """ + +# def __init__(self,fase): +# self.fase = fase + @property def matrix(self): - theta = 0.1234 + theta = 0.5 +# print (theta) +# print ("2.0 * cmath.pi * theta = ", 2.0 * cmath.pi * theta) +# print ("Calculated theta = ", (2.0 * cmath.pi * theta)/(2.0 * cmath.pi)) + return np.matrix([[0,cmath.exp(1j * 2.0 * cmath.pi * theta)], [cmath.exp(1j * 2.0 * cmath.pi * theta),0]]) @@ -77,7 +85,9 @@ def __str__(self): autovector = eng.allocate_qureg(1) H | autovector - unit = PhaseX +# theta = float(input ("Enter phase [0,1): ")) +# print (type(theta),"=====") + unit = PhaseX() print(type(unit)) #### END Defined phase with X ### From 764f60a9675345b06c7e1ae6a4c6fd75bcbc3204 Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 19 Jul 2018 10:25:12 +0200 Subject: [PATCH 08/29] Work in progress: create a PhaseX gate to tests via class. PhaseX testing --- examples/phase_estimation.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 03785886f..9c2a4bc16 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -48,18 +48,15 @@ class PhaseX(BasicGate): A phase gate on X gate with eigenvectors H|0> and HX|0> and eivenvalues exp(i2pi theta) and -exp(i2pi theta) - theta needs to be defined into the class by now """ -# def __init__(self,fase): -# self.fase = fase + def __init__(self,phase): + BasicGate.__init__(self) + self.phase = phase @property def matrix(self): - theta = 0.5 -# print (theta) -# print ("2.0 * cmath.pi * theta = ", 2.0 * cmath.pi * theta) -# print ("Calculated theta = ", (2.0 * cmath.pi * theta)/(2.0 * cmath.pi)) + theta = self.phase return np.matrix([[0,cmath.exp(1j * 2.0 * cmath.pi * theta)], [cmath.exp(1j * 2.0 * cmath.pi * theta),0]]) @@ -83,11 +80,11 @@ def __str__(self): #### Defined phase with X ### + print("Example: Defined phase with X") autovector = eng.allocate_qureg(1) H | autovector -# theta = float(input ("Enter phase [0,1): ")) -# print (type(theta),"=====") - unit = PhaseX() + theta = float(input ("Enter phase [0,1): ")) + unit = PhaseX(theta) print(type(unit)) #### END Defined phase with X ### From d94be6a166d185a3ad22bd36ef1f96ab3b09fc23 Mon Sep 17 00:00:00 2001 From: Fernando Date: Thu, 19 Jul 2018 18:19:40 +0200 Subject: [PATCH 09/29] Work in progress: Debugging algorithm --- examples/phase_estimation.py | 41 +++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 9c2a4bc16..6e8c950da 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -3,6 +3,8 @@ from projectq.meta import Control from projectq import MainEngine +from projectq.backends import CircuitDrawer + import cmath import numpy as np from projectq.ops import (BasicGate) @@ -64,9 +66,24 @@ def matrix(self): def __str__(self): return "PhaseX(theta)" + def tex_str(self): + """ + Return the Latex string representation of a PhaseX Gate. + Returns the class name and the angle as a subscript, i.e. + .. code-block:: latex + [CLASSNAME]$_[ANGLE]$ + """ + + return str("PhX") + "$_{" + str(self.phase) + "}$" + + + if __name__ == "__main__": #Create the compiler engine - eng = MainEngine() + + drawing_engine = CircuitDrawer() + + eng = MainEngine(drawing_engine) # Create the Unitary Operator and the eigenvector unitario = QubitOperator('X0 X1') @@ -82,6 +99,7 @@ def __str__(self): print("Example: Defined phase with X") autovector = eng.allocate_qureg(1) + X | autovector H | autovector theta = float(input ("Enter phase [0,1): ")) unit = PhaseX(theta) @@ -101,19 +119,22 @@ def __str__(self): #======== Testing ==== #unit | autovector - eng.flush() - amp_after1 = eng.backend.get_amplitude('00', autovector) - amp_after2 = eng.backend.get_amplitude('01', autovector) - amp_after3 = eng.backend.get_amplitude('10', autovector) - amp_after4 = eng.backend.get_amplitude('11', autovector) +#== Testing== eng.flush() - print("Amplitude saved in amp_after1: {}".format(amp_after1)) - print("Amplitude saved in amp_after2: {}".format(amp_after2)) - print("Amplitude saved in amp_after3: {}".format(amp_after3)) - print("Amplitude saved in amp_after4: {}".format(amp_after4)) +#== Testing== amp_after1 = eng.backend.get_amplitude('00', autovector) +#== Testing== amp_after2 = eng.backend.get_amplitude('01', autovector) +#== Testing== amp_after3 = eng.backend.get_amplitude('10', autovector) +#== Testing== amp_after4 = eng.backend.get_amplitude('11', autovector) + +#== Testing== print("Amplitude saved in amp_after1: {}".format(amp_after1)) +#== Testing== print("Amplitude saved in amp_after2: {}".format(amp_after2)) +#== Testing== print("Amplitude saved in amp_after3: {}".format(amp_after3)) +#== Testing== print("Amplitude saved in amp_after4: {}".format(amp_after4)) # Deferred measure del estado para que pueda imprimir cosas All(Measure) | autovector eng.flush() + + print(drawing_engine.get_latex()) From 50cf592e6d1baaedf01e1a73f2d5db28701416c8 Mon Sep 17 00:00:00 2001 From: Fernando Date: Fri, 20 Jul 2018 14:19:36 +0200 Subject: [PATCH 10/29] Work in progress: Debugging algorithm --- examples/phase_estimation.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 6e8c950da..4830dda1a 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -22,11 +22,10 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): unitario = unitary for i in range(n_ancillas): + ipower = int(2**i) with Control(eng,ancilla[i]): - unitario | eigenvector - for j in range(i): - with Control(eng,ancilla[i]): - unitario | eigenvector + for j in range(ipower): + unitario | eigenvector # Inverse QFT on the ancilla get_inverse(QFT) | ancilla @@ -36,7 +35,7 @@ def phase_estimation(eng,unitary,eigenvector,n_ancillas): # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) fasebinlist = [int(q) for q in ancilla] - print (fasebinlist, type(fasebinlist)) + print (fasebinlist) fasebin = ''.join(str(j) for j in fasebinlist) faseint = int(fasebin,2) @@ -84,6 +83,7 @@ def tex_str(self): drawing_engine = CircuitDrawer() eng = MainEngine(drawing_engine) +## eng = MainEngine() # Create the Unitary Operator and the eigenvector unitario = QubitOperator('X0 X1') @@ -119,17 +119,18 @@ def tex_str(self): #======== Testing ==== #unit | autovector -#== Testing== eng.flush() + eng.flush() + print(drawing_engine.get_latex(),file=open("pe.tex", "w")) -#== Testing== amp_after1 = eng.backend.get_amplitude('00', autovector) -#== Testing== amp_after2 = eng.backend.get_amplitude('01', autovector) -#== Testing== amp_after3 = eng.backend.get_amplitude('10', autovector) -#== Testing== amp_after4 = eng.backend.get_amplitude('11', autovector) +#======== Testing ==== amp_after1 = eng.backend.get_amplitude('00', autovector) +#======== Testing ==== amp_after2 = eng.backend.get_amplitude('01', autovector) +#======== Testing ==== amp_after3 = eng.backend.get_amplitude('10', autovector) +#======== Testing ==== amp_after4 = eng.backend.get_amplitude('11', autovector) -#== Testing== print("Amplitude saved in amp_after1: {}".format(amp_after1)) -#== Testing== print("Amplitude saved in amp_after2: {}".format(amp_after2)) -#== Testing== print("Amplitude saved in amp_after3: {}".format(amp_after3)) -#== Testing== print("Amplitude saved in amp_after4: {}".format(amp_after4)) +#======== Testing ==== print("Amplitude saved in amp_after1: {}".format(amp_after1)) +#======== Testing ==== print("Amplitude saved in amp_after2: {}".format(amp_after2)) +#======== Testing ==== print("Amplitude saved in amp_after3: {}".format(amp_after3)) +#======== Testing ==== print("Amplitude saved in amp_after4: {}".format(amp_after4)) # Deferred measure del estado para que pueda imprimir cosas @@ -137,4 +138,3 @@ def tex_str(self): eng.flush() - print(drawing_engine.get_latex()) From 9e81bccbd86df2901c61555f5a91704ecbb22a61 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sun, 22 Jul 2018 20:24:37 +0200 Subject: [PATCH 11/29] Adding 2qubit example --- examples/phase_estimation.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 4830dda1a..659e3439d 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -82,12 +82,8 @@ def tex_str(self): drawing_engine = CircuitDrawer() - eng = MainEngine(drawing_engine) -## eng = MainEngine() - - # Create the Unitary Operator and the eigenvector - unitario = QubitOperator('X0 X1') - #unitario = X +## eng = MainEngine(drawing_engine) + eng = MainEngine() ### Example ###unit = TimeEvolution(1.0,unitario) ### Example ###autovector = eng.allocate_qureg(2) @@ -95,15 +91,24 @@ def tex_str(self): ### Example ####unit = X ### Example ####autovector = eng.allocate_qureg(1) - #### Defined phase with X ### + #### Defined phase with X:PhX ### + + ####print("Example: Defined phase with PhX: Example |-> theta: .65625 (.15625) #ancillas:5") + ####autovector = eng.allocate_qureg(1) + ####X | autovector + ####H | autovector + ####theta = float(input ("Enter phase [0,1): ")) + ####unit = PhaseX(theta) + + #### END Defined phase with X:PhX ### + + #### Defined phase with PhX (x) X ### - print("Example: Defined phase with X") - autovector = eng.allocate_qureg(1) - X | autovector - H | autovector - theta = float(input ("Enter phase [0,1): ")) - unit = PhaseX(theta) - print(type(unit)) + print("Example: X (x) X: Example |->|-> theta: NO, NO ES ESTO. Hay que usar TimeEvolution.65625 (.15625) #ancillas:5") + autovector = eng.allocate_qureg(2) + Tensor(X) | autovector + Tensor(H) | autovector + unit = QubitOperator('X0 X1') #### END Defined phase with X ### From 4225eacc55cb23d841f8fc7bbd6f9892fb4b4fd7 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Mon, 23 Jul 2018 21:35:52 +0200 Subject: [PATCH 12/29] adding 2 qubit Gate --- examples/phase_estimation.py | 42 ++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index 659e3439d..f25cb2d9b 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -75,6 +75,40 @@ def tex_str(self): return str("PhX") + "$_{" + str(self.phase) + "}$" +class PhaseXxX(BasicGate): + """ + A phase gate on X (x) X : PhX(x)X gate with + eigenvectors: |+>|+>, |+>|->,|->|+>,|->|->, and + eivenvalues exp(i2pi theta) and -exp(i2pi theta) + """ + + def __init__(self,phase): + BasicGate.__init__(self) + self.phase = phase + + @property + def matrix(self): + theta = self.phase + + return np.matrix([[0,0,0,cmath.exp(1j * 2.0 * cmath.pi * theta)], + [0,0,cmath.exp(1j * 2.0 * cmath.pi * theta),0], + [0,cmath.exp(1j * 2.0 * cmath.pi * theta),0,0], + [cmath.exp(1j * 2.0 * cmath.pi * theta),0,0,0]]) + + def __str__(self): + return "PhaseX(theta)(x)X" + + def tex_str(self): + """ + Return the Latex string representation of a PhaseX Gate. + Returns the class name and the angle as a subscript, i.e. + .. code-block:: latex + [CLASSNAME]$_[ANGLE]$ + """ + + return str("PhX") + "$_{" + str(self.phase) + "}$" + str(" (x) X") + + if __name__ == "__main__": @@ -85,6 +119,9 @@ def tex_str(self): ## eng = MainEngine(drawing_engine) eng = MainEngine() + ### Select an example an uncomment/comment as needed ### + + ### Example ###unit = QubitOperator('X0 X1') ### Example ###unit = TimeEvolution(1.0,unitario) ### Example ###autovector = eng.allocate_qureg(2) @@ -104,11 +141,12 @@ def tex_str(self): #### Defined phase with PhX (x) X ### - print("Example: X (x) X: Example |->|-> theta: NO, NO ES ESTO. Hay que usar TimeEvolution.65625 (.15625) #ancillas:5") + print("Example: PhX (x) X: Example |->|-> theta: .65625 (.15625) #ancillas:5") autovector = eng.allocate_qureg(2) Tensor(X) | autovector Tensor(H) | autovector - unit = QubitOperator('X0 X1') + theta = float(input ("Enter phase [0,1): ")) + unit = PhaseXxX(theta) #### END Defined phase with X ### From 1f9a4f7a03c0091095cb522566658a29bec1d1e6 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sat, 28 Jul 2018 19:31:36 +0200 Subject: [PATCH 13/29] Initial version --- examples/phase_estimation.py | 68 ++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py index f25cb2d9b..f1355e426 100644 --- a/examples/phase_estimation.py +++ b/examples/phase_estimation.py @@ -1,14 +1,13 @@ from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse -from projectq.ops import All, Measure, QubitOperator, TimeEvolution +from projectq.ops import All, Measure from projectq.meta import Control from projectq import MainEngine -from projectq.backends import CircuitDrawer +from projectq.backends import CircuitDrawer, CommandPrinter import cmath import numpy as np from projectq.ops import (BasicGate) -from projectq.types import BasicQubit def phase_estimation(eng,unitary,eigenvector,n_ancillas): @@ -112,58 +111,59 @@ def tex_str(self): if __name__ == "__main__": + #Create the compiler engine - drawing_engine = CircuitDrawer() +#======== Testing ==== drawing_engine = CircuitDrawer() +#======== Testing ==== print_engine = CommandPrinter() -## eng = MainEngine(drawing_engine) +#======== Testing ==== eng = MainEngine(drawing_engine) + eng = MainEngine() - ### Select an example an uncomment/comment as needed ### - - ### Example ###unit = QubitOperator('X0 X1') - ### Example ###unit = TimeEvolution(1.0,unitario) - ### Example ###autovector = eng.allocate_qureg(2) + ### Select an example and uncomment/comment as needed ### - ### Example ####unit = X - ### Example ####autovector = eng.allocate_qureg(1) - - #### Defined phase with X:PhX ### + #### X ### - ####print("Example: Defined phase with PhX: Example |-> theta: .65625 (.15625) #ancillas:5") + ####print("Example: X: Example |-> theta: .5 #ancillas:5") ####autovector = eng.allocate_qureg(1) ####X | autovector ####H | autovector - ####theta = float(input ("Enter phase [0,1): ")) - ####unit = PhaseX(theta) + ####unit = X + + #### END X ### + + #### Defined phase with X:PhX ### + + print("Example: Defined phase with PhX: Example |-> theta: .65625 (.15625) #ancillas:5") + autovector = eng.allocate_qureg(1) + X | autovector + H | autovector + theta = float(input ("Enter phase [0,1): ")) + unit = PhaseX(theta) #### END Defined phase with X:PhX ### #### Defined phase with PhX (x) X ### - print("Example: PhX (x) X: Example |->|-> theta: .65625 (.15625) #ancillas:5") - autovector = eng.allocate_qureg(2) - Tensor(X) | autovector - Tensor(H) | autovector - theta = float(input ("Enter phase [0,1): ")) - unit = PhaseXxX(theta) + ####print("Example: PhX (x) X: Example |->|+> theta: .65625 (.15625) #ancillas:5") + ####autovector = eng.allocate_qureg(2) + ####X | autovector[0] + ####Tensor(H) | autovector + ####theta = float(input ("Enter phase [0,1): ")) + ####unit = PhaseXxX(theta) - #### END Defined phase with X ### - - ### Example ###X | autovector[1] - ### Example ####X | autovector[0] - ### Example ###All(H) | autovector + #### END Defined phase with PhX (x) X ### # Ask for the number of ancillas to use ene = int(input("How many ancillas?: ")) + # Call the phase_estimation function fase = phase_estimation(eng,unit,autovector,ene) -#======== Testing ==== - - #unit | autovector - eng.flush() - print(drawing_engine.get_latex(),file=open("pe.tex", "w")) +#======== Testing ==== eng.flush() + +#======== Testing ==== print(drawing_engine.get_latex(),file=open("pe.tex", "w")) #======== Testing ==== amp_after1 = eng.backend.get_amplitude('00', autovector) #======== Testing ==== amp_after2 = eng.backend.get_amplitude('01', autovector) @@ -175,7 +175,7 @@ def tex_str(self): #======== Testing ==== print("Amplitude saved in amp_after3: {}".format(amp_after3)) #======== Testing ==== print("Amplitude saved in amp_after4: {}".format(amp_after4)) - # Deferred measure del estado para que pueda imprimir cosas + # Deferred measure of the state in order to be print All(Measure) | autovector From 54e7cc2ab123be89702067b72d56980c923bf249 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sat, 18 Aug 2018 11:43:08 +0200 Subject: [PATCH 14/29] Create Phase Estimation as a new Gate in operations --- docs/projectq.ops.rst | 1 + projectq/ops/__init__.py | 1 + projectq/ops/_phase_estimation.py | 112 +++++++++++++ projectq/ops/_phase_estimation_test.py | 219 +++++++++++++++++++++++++ 4 files changed, 333 insertions(+) create mode 100644 projectq/ops/_phase_estimation.py create mode 100644 projectq/ops/_phase_estimation_test.py diff --git a/docs/projectq.ops.rst b/docs/projectq.ops.rst index 8f8d4cceb..6acf4586a 100755 --- a/docs/projectq.ops.rst +++ b/docs/projectq.ops.rst @@ -52,6 +52,7 @@ The operations collection consists of various default gates and is a work-in-pro projectq.ops.UniformlyControlledRy projectq.ops.UniformlyControlledRz projectq.ops.StatePreparation + projectq.ops.PhaseEstimation Module contents diff --git a/projectq/ops/__init__.py b/projectq/ops/__init__.py index 32ff8ab54..d11419187 100755 --- a/projectq/ops/__init__.py +++ b/projectq/ops/__init__.py @@ -36,3 +36,4 @@ from ._uniformly_controlled_rotation import (UniformlyControlledRy, UniformlyControlledRz) from ._state_prep import StatePreparation +from ._phase_estimation import PhaseEstimation diff --git a/projectq/ops/_phase_estimation.py b/projectq/ops/_phase_estimation.py new file mode 100644 index 000000000..dffa49c24 --- /dev/null +++ b/projectq/ops/_phase_estimation.py @@ -0,0 +1,112 @@ +# Copyright 2018 ProjectQ-Framework (www.projectq.ch) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from projectq.ops import H, Tensor, C +from ._basics import BasicGate + +class PhaseEstimation(BasicGate): + """ + Gate for phase estimation for a unitary operation U. + + This gate executes teh algorith of phase estimation up to just before the + inverse QFT on the ancillas + + (reference https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) + + This allows to use externally to the gate any QFT schema as a semi-classical one. + + The gate is applied to a qureg of ancillas and a qureg of system qubits and use + as a parameter the unitary operator U. + + After Phase Estimation gate is applied the ancillas are prepared to inverse QFT + for phase (eigenvalue) extraction and the system quibits end in the corresponding + eigenvector. + + + Example: + .. code-block:: python + + n_qpe_ancillas = 5 + qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas) + system_qubits = eng.allocate_qureg(2) + U = unitary_specfic_to_the_problem() + + # Apply Quantum Phase Estimation + PhaseEstimation(unitary = U) | (qpe_ancillas, system_qubits) + + # Apply an inverse QFT and measure to the ancillas + get_inverse(QFT) | qpe_ancillas + All(Measure) | qpe_ancillas + # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) + phasebinlist = [int(q) for q in qpe_ancillas] + phase_in_bin = ''.join(str(j) for j in phasebinlist) + phase_int = int(phase_in_bin,2) + phase = phase_int / (2 ** n_qpe_ancillas) + + Attributes: + unitary (BasicGate): Unitary Operation U + + """ + def __init__(self, unitary): + """ + Initialize Phase Estimation gate. + + Note: + The unitary must by an unitary operation + + Args: + unitary (BasicGate): unitary operation for which we want to obtain + the eigenvalues and eigenvectors + + Raises: + TypeError: If unitary is not a BasicGate + """ + BasicGate.__init__(self) + self.unitary = unitary + + + def __or__(self, qubits): + """ + Apply Tensor(H) to the qpe_ancillas + + Apply the controlled-unitary gate to system_qubits in powers depending on the + numeral of the ancilla qubit (see the reference) + Args: + qpe_ancillas (qureg object): ancillas of the algorithm + system_qubits (qureg object): qubits on which the unitary is applied and which + are eigenvector of U or combination of eigenvectors of U + """ + + qubits = self.make_tuple_of_qureg(qubits) + if len(qubits) != 2: + raise TypeError("Only two qubit or qureg are allowed.") + + # Ancillas is the first qubit/qureg. System-qubit is the second qubit/qureg + + qpe_ancillas = qubits[0] + system_qubits = qubits[1] + + # Hadamard on the ancillas + Tensor(H) | qpe_ancillas + + # Control U on the eigenvector + operator = self.unitary + + for i in range(len(qpe_ancillas)): + ipower = int(2**i) + for j in range(ipower): + C(operator) | (qpe_ancillas[i],system_qubits) + + def __str__(self): + return "PhaseEstimation" diff --git a/projectq/ops/_phase_estimation_test.py b/projectq/ops/_phase_estimation_test.py new file mode 100644 index 000000000..af3013c23 --- /dev/null +++ b/projectq/ops/_phase_estimation_test.py @@ -0,0 +1,219 @@ +# Copyright 2018 ProjectQ-Framework (www.projectq.ch) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for projectq.ops._phase_estimation.""" + +import copy +import cmath +import numpy as np +import pytest + +from projectq import MainEngine +from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse,StatePreparation +from projectq.ops import All, Measure + +from projectq.ops import (BasicGate) + +from projectq.ops import _phase_estimation as pe + + +class PhaseX(BasicGate): + """ + A phase gate on X gate with + eigenvectors H|0> and HX|0> and + eivenvalues exp(i2pi theta) and -exp(i2pi theta) + """ + + def __init__(self,phase): + BasicGate.__init__(self) + self.phase = phase + + @property + def matrix(self): + theta = self.phase + + return np.matrix([[0,cmath.exp(1j * 2.0 * cmath.pi * theta)], + [cmath.exp(1j * 2.0 * cmath.pi * theta),0]]) + + def __str__(self): + return "PhaseX(theta)" + + def tex_str(self): + """ + Return the Latex string representation of a PhaseX Gate. + Returns the class name and the angle as a subscript, i.e. + .. code-block:: latex + [CLASSNAME]$_[ANGLE]$ + """ + + return str("PhX") + "$_{" + str(self.phase) + "}$" + +class PhaseXxX(BasicGate): + """ + A phase gate on X (x) X : PhX(x)X gate with + eigenvectors: |+>|+>, |+>|->,|->|+>,|->|->, and + eivenvalues exp(i2pi theta) and -exp(i2pi theta) + """ + + def __init__(self,phase): + BasicGate.__init__(self) + self.phase = phase + + @property + def matrix(self): + theta = self.phase + + return np.matrix([[0,0,0,cmath.exp(1j * 2.0 * cmath.pi * theta)], + [0,0,cmath.exp(1j * 2.0 * cmath.pi * theta),0], + [0,cmath.exp(1j * 2.0 * cmath.pi * theta),0,0], + [cmath.exp(1j * 2.0 * cmath.pi * theta),0,0,0]]) + + def __str__(self): + return "PhaseX(theta)(x)X" + + def tex_str(self): + """ + Return the Latex string representation of a PhaseX Gate. + Returns the class name and the angle as a subscript, i.e. + .. code-block:: latex + [CLASSNAME]$_[ANGLE]$ + """ + + return str("PhX") + "$_{" + str(self.phase) + "}$" + str(" (x) X") + + +def simple_test_X_eigenvectors(): + eng = MainEngine() + results = np.array([]) + for i in range(10): + autovector = eng.allocate_qureg(1) + X | autovector + H | autovector + unit = X + ancillas = eng.allocate_qureg(1) + pe.PhaseEstimation(unit) | (ancillas,autovector) + get_inverse(QFT) | ancillas + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin,2) + phase = faseint / (2 ** (len(ancillas))) + results = np.append(results,phase) + All(Measure) | autovector + eng.flush() + + perc_95 = np.percentile(results,95) + assert perc_95 == 0.5 + +def test_phaseX_eigenvectors_minus(): + eng = MainEngine() + results = np.array([]) + for i in range(10): + autovector = eng.allocate_qureg(1) + X | autovector + H | autovector + theta = .15625 + unit = PhaseX(theta) + ancillas = eng.allocate_qureg(5) + pe.PhaseEstimation(unit) | (ancillas,autovector) + get_inverse(QFT) | ancillas + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin,2) + phase = faseint / (2 ** (len(ancillas))) + results = np.append(results,phase) + All(Measure) | autovector + eng.flush() + + perc_75 = np.percentile(results,75) + assert perc_75 == pytest.approx(.65625, abs=1e-2) + +def test_phaseXxX_eigenvectors_minusplus(): + eng = MainEngine() + results = np.array([]) + for i in range(10): + autovector = eng.allocate_qureg(2) + X | autovector[0] + Tensor(H) | autovector + theta = .15625 + unit = PhaseXxX(theta) + ancillas = eng.allocate_qureg(5) + pe.PhaseEstimation(unit) | (ancillas,autovector) + get_inverse(QFT) | ancillas + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin,2) + phase = faseint / (2 ** (len(ancillas))) + results = np.append(results,phase) + All(Measure) | autovector + eng.flush() + + perc_75 = np.percentile(results,75) + assert perc_75 == pytest.approx(.65625, abs=1e-2) + +def test_X_no_eigenvectors(): + eng = MainEngine() + results = np.array([]) + results_plus = np.array([]) + results_minus = np.array([]) + for i in range(100): + autovector = eng.allocate_qureg(1) + amplitude0 = (np.sqrt(2) + np.sqrt(6))/2. + amplitude1 = (np.sqrt(2) - np.sqrt(6))/2. + StatePreparation([amplitude0, amplitude1]) | autovector + unit = X + ancillas = eng.allocate_qureg(1) + pe.PhaseEstimation(unit) | (ancillas,autovector) + get_inverse(QFT) | ancillas + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin,2) + phase = faseint / (2 ** (len(ancillas))) + results = np.append(results,phase) + Tensor(H) | autovector + if np.allclose(phase,.0,rtol=1e-1): + results_plus = np.append(results_plus,phase) + All(Measure) | autovector + autovector_result = int(autovector) + assert autovector_result == 0 + elif np.allclose(phase,.5,rtol=1e-1): + results_minus = np.append(results_minus,phase) + All(Measure) | autovector + autovector_result = int(autovector) + assert autovector_result == 1 + else: + All(Measure) | autovector + + eng.flush() + + total = len(results_plus) + len(results_minus) + ratio = len(results_plus)/len(results_minus) + assert total == pytest.approx(100,abs=5) + assert ratio == pytest.approx(1./3., abs = 1e-1), "Statistical ratio is not correct (%f %d %d)" % (ratio,len(results_plus),len(results_minus)) + + +def test_n_qureg(): + eng = MainEngine() + autovector = eng.allocate_qureg(1) + ancillas = eng.allocate_qureg(1) + unit = X + with pytest.raises(TypeError): + pe.PhaseEstimation(unit) | (ancillas,autovector,autovector) + with pytest.raises(TypeError): + pe.PhaseEstimation(unit) | ancillas + + From ac03bdc8308d4cba7c50f05d93b260713747bb63 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sat, 18 Aug 2018 12:11:12 +0200 Subject: [PATCH 15/29] Solving travis checks --- examples/phase_estimation.py | 183 ------------------------- projectq/ops/_phase_estimation_test.py | 5 +- 2 files changed, 2 insertions(+), 186 deletions(-) delete mode 100644 examples/phase_estimation.py diff --git a/examples/phase_estimation.py b/examples/phase_estimation.py deleted file mode 100644 index f1355e426..000000000 --- a/examples/phase_estimation.py +++ /dev/null @@ -1,183 +0,0 @@ -from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse -from projectq.ops import All, Measure -from projectq.meta import Control -from projectq import MainEngine - -from projectq.backends import CircuitDrawer, CommandPrinter - -import cmath -import numpy as np -from projectq.ops import (BasicGate) - -def phase_estimation(eng,unitary,eigenvector,n_ancillas): - - # create the ancillas and are left to |0> - ancilla = eng.allocate_qureg(n_ancillas) - - # Hadamard on the ancillas - Tensor(H) | ancilla - - # Control U on the eigenvector - unitario = unitary - - for i in range(n_ancillas): - ipower = int(2**i) - with Control(eng,ancilla[i]): - for j in range(ipower): - unitario | eigenvector - - # Inverse QFT on the ancilla - get_inverse(QFT) | ancilla - - # Ancilla measurement - All(Measure) | ancilla - - # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) - fasebinlist = [int(q) for q in ancilla] - print (fasebinlist) - - fasebin = ''.join(str(j) for j in fasebinlist) - faseint = int(fasebin,2) - fase = faseint / (2 ** n_ancillas) - - print (fasebin, faseint,"fase final = ", fase) - return fase - -class PhaseX(BasicGate): - """ - A phase gate on X gate with - eigenvectors H|0> and HX|0> and - eivenvalues exp(i2pi theta) and -exp(i2pi theta) - """ - - def __init__(self,phase): - BasicGate.__init__(self) - self.phase = phase - - @property - def matrix(self): - theta = self.phase - - return np.matrix([[0,cmath.exp(1j * 2.0 * cmath.pi * theta)], - [cmath.exp(1j * 2.0 * cmath.pi * theta),0]]) - - def __str__(self): - return "PhaseX(theta)" - - def tex_str(self): - """ - Return the Latex string representation of a PhaseX Gate. - Returns the class name and the angle as a subscript, i.e. - .. code-block:: latex - [CLASSNAME]$_[ANGLE]$ - """ - - return str("PhX") + "$_{" + str(self.phase) + "}$" - -class PhaseXxX(BasicGate): - """ - A phase gate on X (x) X : PhX(x)X gate with - eigenvectors: |+>|+>, |+>|->,|->|+>,|->|->, and - eivenvalues exp(i2pi theta) and -exp(i2pi theta) - """ - - def __init__(self,phase): - BasicGate.__init__(self) - self.phase = phase - - @property - def matrix(self): - theta = self.phase - - return np.matrix([[0,0,0,cmath.exp(1j * 2.0 * cmath.pi * theta)], - [0,0,cmath.exp(1j * 2.0 * cmath.pi * theta),0], - [0,cmath.exp(1j * 2.0 * cmath.pi * theta),0,0], - [cmath.exp(1j * 2.0 * cmath.pi * theta),0,0,0]]) - - def __str__(self): - return "PhaseX(theta)(x)X" - - def tex_str(self): - """ - Return the Latex string representation of a PhaseX Gate. - Returns the class name and the angle as a subscript, i.e. - .. code-block:: latex - [CLASSNAME]$_[ANGLE]$ - """ - - return str("PhX") + "$_{" + str(self.phase) + "}$" + str(" (x) X") - - - - -if __name__ == "__main__": - - #Create the compiler engine - -#======== Testing ==== drawing_engine = CircuitDrawer() -#======== Testing ==== print_engine = CommandPrinter() - -#======== Testing ==== eng = MainEngine(drawing_engine) - - eng = MainEngine() - - ### Select an example and uncomment/comment as needed ### - - #### X ### - - ####print("Example: X: Example |-> theta: .5 #ancillas:5") - ####autovector = eng.allocate_qureg(1) - ####X | autovector - ####H | autovector - ####unit = X - - #### END X ### - - #### Defined phase with X:PhX ### - - print("Example: Defined phase with PhX: Example |-> theta: .65625 (.15625) #ancillas:5") - autovector = eng.allocate_qureg(1) - X | autovector - H | autovector - theta = float(input ("Enter phase [0,1): ")) - unit = PhaseX(theta) - - #### END Defined phase with X:PhX ### - - #### Defined phase with PhX (x) X ### - - ####print("Example: PhX (x) X: Example |->|+> theta: .65625 (.15625) #ancillas:5") - ####autovector = eng.allocate_qureg(2) - ####X | autovector[0] - ####Tensor(H) | autovector - ####theta = float(input ("Enter phase [0,1): ")) - ####unit = PhaseXxX(theta) - - #### END Defined phase with PhX (x) X ### - - # Ask for the number of ancillas to use - ene = int(input("How many ancillas?: ")) - - # Call the phase_estimation function - fase = phase_estimation(eng,unit,autovector,ene) - -#======== Testing ==== eng.flush() - -#======== Testing ==== print(drawing_engine.get_latex(),file=open("pe.tex", "w")) - -#======== Testing ==== amp_after1 = eng.backend.get_amplitude('00', autovector) -#======== Testing ==== amp_after2 = eng.backend.get_amplitude('01', autovector) -#======== Testing ==== amp_after3 = eng.backend.get_amplitude('10', autovector) -#======== Testing ==== amp_after4 = eng.backend.get_amplitude('11', autovector) - -#======== Testing ==== print("Amplitude saved in amp_after1: {}".format(amp_after1)) -#======== Testing ==== print("Amplitude saved in amp_after2: {}".format(amp_after2)) -#======== Testing ==== print("Amplitude saved in amp_after3: {}".format(amp_after3)) -#======== Testing ==== print("Amplitude saved in amp_after4: {}".format(amp_after4)) - - # Deferred measure of the state in order to be print - - All(Measure) | autovector - - eng.flush() - diff --git a/projectq/ops/_phase_estimation_test.py b/projectq/ops/_phase_estimation_test.py index af3013c23..d4c57b395 100644 --- a/projectq/ops/_phase_estimation_test.py +++ b/projectq/ops/_phase_estimation_test.py @@ -138,7 +138,7 @@ def test_phaseX_eigenvectors_minus(): eng.flush() perc_75 = np.percentile(results,75) - assert perc_75 == pytest.approx(.65625, abs=1e-2) + assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) def test_phaseXxX_eigenvectors_minusplus(): eng = MainEngine() @@ -162,7 +162,7 @@ def test_phaseXxX_eigenvectors_minusplus(): eng.flush() perc_75 = np.percentile(results,75) - assert perc_75 == pytest.approx(.65625, abs=1e-2) + assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) def test_X_no_eigenvectors(): eng = MainEngine() @@ -197,7 +197,6 @@ def test_X_no_eigenvectors(): assert autovector_result == 1 else: All(Measure) | autovector - eng.flush() total = len(results_plus) + len(results_minus) From 2d37dd45049eab1a848a7565dab0ef2b97d0088f Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sat, 18 Aug 2018 13:20:16 +0200 Subject: [PATCH 16/29] python 2 compatibility + error in StatePreparation normalization --- projectq/ops/_phase_estimation_test.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/projectq/ops/_phase_estimation_test.py b/projectq/ops/_phase_estimation_test.py index d4c57b395..fedbe9ca4 100644 --- a/projectq/ops/_phase_estimation_test.py +++ b/projectq/ops/_phase_estimation_test.py @@ -108,7 +108,7 @@ def simple_test_X_eigenvectors(): fasebinlist = [int(q) for q in ancillas] fasebin = ''.join(str(j) for j in fasebinlist) faseint = int(fasebin,2) - phase = faseint / (2 ** (len(ancillas))) + phase = faseint / (2. ** (len(ancillas))) results = np.append(results,phase) All(Measure) | autovector eng.flush() @@ -132,7 +132,7 @@ def test_phaseX_eigenvectors_minus(): fasebinlist = [int(q) for q in ancillas] fasebin = ''.join(str(j) for j in fasebinlist) faseint = int(fasebin,2) - phase = faseint / (2 ** (len(ancillas))) + phase = faseint / (2. ** (len(ancillas))) results = np.append(results,phase) All(Measure) | autovector eng.flush() @@ -156,7 +156,7 @@ def test_phaseXxX_eigenvectors_minusplus(): fasebinlist = [int(q) for q in ancillas] fasebin = ''.join(str(j) for j in fasebinlist) faseint = int(fasebin,2) - phase = faseint / (2 ** (len(ancillas))) + phase = faseint / (2. ** (len(ancillas))) results = np.append(results,phase) All(Measure) | autovector eng.flush() @@ -171,8 +171,8 @@ def test_X_no_eigenvectors(): results_minus = np.array([]) for i in range(100): autovector = eng.allocate_qureg(1) - amplitude0 = (np.sqrt(2) + np.sqrt(6))/2. - amplitude1 = (np.sqrt(2) - np.sqrt(6))/2. + amplitude0 = (np.sqrt(2) + np.sqrt(6))/4. + amplitude1 = (np.sqrt(2) - np.sqrt(6))/4. StatePreparation([amplitude0, amplitude1]) | autovector unit = X ancillas = eng.allocate_qureg(1) @@ -182,7 +182,7 @@ def test_X_no_eigenvectors(): fasebinlist = [int(q) for q in ancillas] fasebin = ''.join(str(j) for j in fasebinlist) faseint = int(fasebin,2) - phase = faseint / (2 ** (len(ancillas))) + phase = faseint / (2. ** (len(ancillas))) results = np.append(results,phase) Tensor(H) | autovector if np.allclose(phase,.0,rtol=1e-1): @@ -200,7 +200,7 @@ def test_X_no_eigenvectors(): eng.flush() total = len(results_plus) + len(results_minus) - ratio = len(results_plus)/len(results_minus) + ratio = float(len(results_plus))/float(len(results_minus)) assert total == pytest.approx(100,abs=5) assert ratio == pytest.approx(1./3., abs = 1e-1), "Statistical ratio is not correct (%f %d %d)" % (ratio,len(results_plus),len(results_minus)) @@ -214,5 +214,3 @@ def test_n_qureg(): pe.PhaseEstimation(unit) | (ancillas,autovector,autovector) with pytest.raises(TypeError): pe.PhaseEstimation(unit) | ancillas - - From 8876d34545f10d9e7ae9d5eaab2abd49fc493481 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sat, 18 Aug 2018 14:22:31 +0200 Subject: [PATCH 17/29] test coverage includes now the string --- projectq/ops/_phase_estimation_test.py | 32 +++++--------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/projectq/ops/_phase_estimation_test.py b/projectq/ops/_phase_estimation_test.py index fedbe9ca4..8fdba14e4 100644 --- a/projectq/ops/_phase_estimation_test.py +++ b/projectq/ops/_phase_estimation_test.py @@ -46,19 +46,6 @@ def matrix(self): return np.matrix([[0,cmath.exp(1j * 2.0 * cmath.pi * theta)], [cmath.exp(1j * 2.0 * cmath.pi * theta),0]]) - def __str__(self): - return "PhaseX(theta)" - - def tex_str(self): - """ - Return the Latex string representation of a PhaseX Gate. - Returns the class name and the angle as a subscript, i.e. - .. code-block:: latex - [CLASSNAME]$_[ANGLE]$ - """ - - return str("PhX") + "$_{" + str(self.phase) + "}$" - class PhaseXxX(BasicGate): """ A phase gate on X (x) X : PhX(x)X gate with @@ -79,19 +66,6 @@ def matrix(self): [0,cmath.exp(1j * 2.0 * cmath.pi * theta),0,0], [cmath.exp(1j * 2.0 * cmath.pi * theta),0,0,0]]) - def __str__(self): - return "PhaseX(theta)(x)X" - - def tex_str(self): - """ - Return the Latex string representation of a PhaseX Gate. - Returns the class name and the angle as a subscript, i.e. - .. code-block:: latex - [CLASSNAME]$_[ANGLE]$ - """ - - return str("PhX") + "$_{" + str(self.phase) + "}$" + str(" (x) X") - def simple_test_X_eigenvectors(): eng = MainEngine() @@ -214,3 +188,9 @@ def test_n_qureg(): pe.PhaseEstimation(unit) | (ancillas,autovector,autovector) with pytest.raises(TypeError): pe.PhaseEstimation(unit) | ancillas + +def test_string(): + unit = X + gate = pe.PhaseEstimation(unit) + assert (str(gate) == "PhaseEstimation") + From ed82caedf94bbd0ceab18e8929fda4d79a328215 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sun, 19 Aug 2018 12:42:48 +0200 Subject: [PATCH 18/29] Improve the check test for no eigenvector test --- projectq/ops/_phase_estimation_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projectq/ops/_phase_estimation_test.py b/projectq/ops/_phase_estimation_test.py index 8fdba14e4..2346f2abb 100644 --- a/projectq/ops/_phase_estimation_test.py +++ b/projectq/ops/_phase_estimation_test.py @@ -174,9 +174,9 @@ def test_X_no_eigenvectors(): eng.flush() total = len(results_plus) + len(results_minus) - ratio = float(len(results_plus))/float(len(results_minus)) + plus_probability = len(results_plus)/100. assert total == pytest.approx(100,abs=5) - assert ratio == pytest.approx(1./3., abs = 1e-1), "Statistical ratio is not correct (%f %d %d)" % (ratio,len(results_plus),len(results_minus)) + assert plus_probability == pytest.approx(1./4., abs = 1e-1), "Statistics on |+> probability are not correct (%f vs. %f)" % (plus_probability,1./4.) def test_n_qureg(): From 77a84b30c546fb311ac5b2f9a7db2fbffff4f0df Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sun, 16 Dec 2018 21:30:15 +0100 Subject: [PATCH 19/29] Start modifying to decomposition --- docs/projectq.ops.rst | 2 +- projectq/ops/__init__.py | 2 +- projectq/ops/_phase_estimation.py | 112 ---------- projectq/ops/_phase_estimation_test.py | 196 ------------------ projectq/ops/_qpegate.py | 29 +++ projectq/ops/_qpegate_test.py | 25 +++ .../setups/decompositions/phaseestimation.py | 125 +++++++++++ .../decompositions/phaseestimation_test.py | 42 ++++ 8 files changed, 223 insertions(+), 310 deletions(-) delete mode 100644 projectq/ops/_phase_estimation.py delete mode 100644 projectq/ops/_phase_estimation_test.py create mode 100755 projectq/ops/_qpegate.py create mode 100755 projectq/ops/_qpegate_test.py create mode 100644 projectq/setups/decompositions/phaseestimation.py create mode 100644 projectq/setups/decompositions/phaseestimation_test.py diff --git a/docs/projectq.ops.rst b/docs/projectq.ops.rst index 6acf4586a..9e4b8768a 100755 --- a/docs/projectq.ops.rst +++ b/docs/projectq.ops.rst @@ -52,7 +52,7 @@ The operations collection consists of various default gates and is a work-in-pro projectq.ops.UniformlyControlledRy projectq.ops.UniformlyControlledRz projectq.ops.StatePreparation - projectq.ops.PhaseEstimation + projectq.ops.QPE Module contents diff --git a/projectq/ops/__init__.py b/projectq/ops/__init__.py index d11419187..d67ec3781 100755 --- a/projectq/ops/__init__.py +++ b/projectq/ops/__init__.py @@ -36,4 +36,4 @@ from ._uniformly_controlled_rotation import (UniformlyControlledRy, UniformlyControlledRz) from ._state_prep import StatePreparation -from ._phase_estimation import PhaseEstimation +from ._qpegate import QPE diff --git a/projectq/ops/_phase_estimation.py b/projectq/ops/_phase_estimation.py deleted file mode 100644 index dffa49c24..000000000 --- a/projectq/ops/_phase_estimation.py +++ /dev/null @@ -1,112 +0,0 @@ -# Copyright 2018 ProjectQ-Framework (www.projectq.ch) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from projectq.ops import H, Tensor, C -from ._basics import BasicGate - -class PhaseEstimation(BasicGate): - """ - Gate for phase estimation for a unitary operation U. - - This gate executes teh algorith of phase estimation up to just before the - inverse QFT on the ancillas - - (reference https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) - - This allows to use externally to the gate any QFT schema as a semi-classical one. - - The gate is applied to a qureg of ancillas and a qureg of system qubits and use - as a parameter the unitary operator U. - - After Phase Estimation gate is applied the ancillas are prepared to inverse QFT - for phase (eigenvalue) extraction and the system quibits end in the corresponding - eigenvector. - - - Example: - .. code-block:: python - - n_qpe_ancillas = 5 - qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas) - system_qubits = eng.allocate_qureg(2) - U = unitary_specfic_to_the_problem() - - # Apply Quantum Phase Estimation - PhaseEstimation(unitary = U) | (qpe_ancillas, system_qubits) - - # Apply an inverse QFT and measure to the ancillas - get_inverse(QFT) | qpe_ancillas - All(Measure) | qpe_ancillas - # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) - phasebinlist = [int(q) for q in qpe_ancillas] - phase_in_bin = ''.join(str(j) for j in phasebinlist) - phase_int = int(phase_in_bin,2) - phase = phase_int / (2 ** n_qpe_ancillas) - - Attributes: - unitary (BasicGate): Unitary Operation U - - """ - def __init__(self, unitary): - """ - Initialize Phase Estimation gate. - - Note: - The unitary must by an unitary operation - - Args: - unitary (BasicGate): unitary operation for which we want to obtain - the eigenvalues and eigenvectors - - Raises: - TypeError: If unitary is not a BasicGate - """ - BasicGate.__init__(self) - self.unitary = unitary - - - def __or__(self, qubits): - """ - Apply Tensor(H) to the qpe_ancillas - - Apply the controlled-unitary gate to system_qubits in powers depending on the - numeral of the ancilla qubit (see the reference) - Args: - qpe_ancillas (qureg object): ancillas of the algorithm - system_qubits (qureg object): qubits on which the unitary is applied and which - are eigenvector of U or combination of eigenvectors of U - """ - - qubits = self.make_tuple_of_qureg(qubits) - if len(qubits) != 2: - raise TypeError("Only two qubit or qureg are allowed.") - - # Ancillas is the first qubit/qureg. System-qubit is the second qubit/qureg - - qpe_ancillas = qubits[0] - system_qubits = qubits[1] - - # Hadamard on the ancillas - Tensor(H) | qpe_ancillas - - # Control U on the eigenvector - operator = self.unitary - - for i in range(len(qpe_ancillas)): - ipower = int(2**i) - for j in range(ipower): - C(operator) | (qpe_ancillas[i],system_qubits) - - def __str__(self): - return "PhaseEstimation" diff --git a/projectq/ops/_phase_estimation_test.py b/projectq/ops/_phase_estimation_test.py deleted file mode 100644 index 2346f2abb..000000000 --- a/projectq/ops/_phase_estimation_test.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright 2018 ProjectQ-Framework (www.projectq.ch) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Tests for projectq.ops._phase_estimation.""" - -import copy -import cmath -import numpy as np -import pytest - -from projectq import MainEngine -from projectq.ops import H, X, Y, Z, Tensor, QFT, get_inverse,StatePreparation -from projectq.ops import All, Measure - -from projectq.ops import (BasicGate) - -from projectq.ops import _phase_estimation as pe - - -class PhaseX(BasicGate): - """ - A phase gate on X gate with - eigenvectors H|0> and HX|0> and - eivenvalues exp(i2pi theta) and -exp(i2pi theta) - """ - - def __init__(self,phase): - BasicGate.__init__(self) - self.phase = phase - - @property - def matrix(self): - theta = self.phase - - return np.matrix([[0,cmath.exp(1j * 2.0 * cmath.pi * theta)], - [cmath.exp(1j * 2.0 * cmath.pi * theta),0]]) - -class PhaseXxX(BasicGate): - """ - A phase gate on X (x) X : PhX(x)X gate with - eigenvectors: |+>|+>, |+>|->,|->|+>,|->|->, and - eivenvalues exp(i2pi theta) and -exp(i2pi theta) - """ - - def __init__(self,phase): - BasicGate.__init__(self) - self.phase = phase - - @property - def matrix(self): - theta = self.phase - - return np.matrix([[0,0,0,cmath.exp(1j * 2.0 * cmath.pi * theta)], - [0,0,cmath.exp(1j * 2.0 * cmath.pi * theta),0], - [0,cmath.exp(1j * 2.0 * cmath.pi * theta),0,0], - [cmath.exp(1j * 2.0 * cmath.pi * theta),0,0,0]]) - - -def simple_test_X_eigenvectors(): - eng = MainEngine() - results = np.array([]) - for i in range(10): - autovector = eng.allocate_qureg(1) - X | autovector - H | autovector - unit = X - ancillas = eng.allocate_qureg(1) - pe.PhaseEstimation(unit) | (ancillas,autovector) - get_inverse(QFT) | ancillas - All(Measure) | ancillas - fasebinlist = [int(q) for q in ancillas] - fasebin = ''.join(str(j) for j in fasebinlist) - faseint = int(fasebin,2) - phase = faseint / (2. ** (len(ancillas))) - results = np.append(results,phase) - All(Measure) | autovector - eng.flush() - - perc_95 = np.percentile(results,95) - assert perc_95 == 0.5 - -def test_phaseX_eigenvectors_minus(): - eng = MainEngine() - results = np.array([]) - for i in range(10): - autovector = eng.allocate_qureg(1) - X | autovector - H | autovector - theta = .15625 - unit = PhaseX(theta) - ancillas = eng.allocate_qureg(5) - pe.PhaseEstimation(unit) | (ancillas,autovector) - get_inverse(QFT) | ancillas - All(Measure) | ancillas - fasebinlist = [int(q) for q in ancillas] - fasebin = ''.join(str(j) for j in fasebinlist) - faseint = int(fasebin,2) - phase = faseint / (2. ** (len(ancillas))) - results = np.append(results,phase) - All(Measure) | autovector - eng.flush() - - perc_75 = np.percentile(results,75) - assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) - -def test_phaseXxX_eigenvectors_minusplus(): - eng = MainEngine() - results = np.array([]) - for i in range(10): - autovector = eng.allocate_qureg(2) - X | autovector[0] - Tensor(H) | autovector - theta = .15625 - unit = PhaseXxX(theta) - ancillas = eng.allocate_qureg(5) - pe.PhaseEstimation(unit) | (ancillas,autovector) - get_inverse(QFT) | ancillas - All(Measure) | ancillas - fasebinlist = [int(q) for q in ancillas] - fasebin = ''.join(str(j) for j in fasebinlist) - faseint = int(fasebin,2) - phase = faseint / (2. ** (len(ancillas))) - results = np.append(results,phase) - All(Measure) | autovector - eng.flush() - - perc_75 = np.percentile(results,75) - assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) - -def test_X_no_eigenvectors(): - eng = MainEngine() - results = np.array([]) - results_plus = np.array([]) - results_minus = np.array([]) - for i in range(100): - autovector = eng.allocate_qureg(1) - amplitude0 = (np.sqrt(2) + np.sqrt(6))/4. - amplitude1 = (np.sqrt(2) - np.sqrt(6))/4. - StatePreparation([amplitude0, amplitude1]) | autovector - unit = X - ancillas = eng.allocate_qureg(1) - pe.PhaseEstimation(unit) | (ancillas,autovector) - get_inverse(QFT) | ancillas - All(Measure) | ancillas - fasebinlist = [int(q) for q in ancillas] - fasebin = ''.join(str(j) for j in fasebinlist) - faseint = int(fasebin,2) - phase = faseint / (2. ** (len(ancillas))) - results = np.append(results,phase) - Tensor(H) | autovector - if np.allclose(phase,.0,rtol=1e-1): - results_plus = np.append(results_plus,phase) - All(Measure) | autovector - autovector_result = int(autovector) - assert autovector_result == 0 - elif np.allclose(phase,.5,rtol=1e-1): - results_minus = np.append(results_minus,phase) - All(Measure) | autovector - autovector_result = int(autovector) - assert autovector_result == 1 - else: - All(Measure) | autovector - eng.flush() - - total = len(results_plus) + len(results_minus) - plus_probability = len(results_plus)/100. - assert total == pytest.approx(100,abs=5) - assert plus_probability == pytest.approx(1./4., abs = 1e-1), "Statistics on |+> probability are not correct (%f vs. %f)" % (plus_probability,1./4.) - - -def test_n_qureg(): - eng = MainEngine() - autovector = eng.allocate_qureg(1) - ancillas = eng.allocate_qureg(1) - unit = X - with pytest.raises(TypeError): - pe.PhaseEstimation(unit) | (ancillas,autovector,autovector) - with pytest.raises(TypeError): - pe.PhaseEstimation(unit) | ancillas - -def test_string(): - unit = X - gate = pe.PhaseEstimation(unit) - assert (str(gate) == "PhaseEstimation") - diff --git a/projectq/ops/_qpegate.py b/projectq/ops/_qpegate.py new file mode 100755 index 000000000..4058807ce --- /dev/null +++ b/projectq/ops/_qpegate.py @@ -0,0 +1,29 @@ +# Copyright 2017 ProjectQ-Framework (www.projectq.ch) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from ._basics import BasicGate + + +class QPE(BasicGate): + """ + Quantum Phase Estimation gate. + + See setups.decompositions for the complete implementation + """ + def __init__(self, unitary): + BasicGate.__init__(self) + self.unitary = unitary + + def __str__(self): + return "QPE_"+str(self.unitary) diff --git a/projectq/ops/_qpegate_test.py b/projectq/ops/_qpegate_test.py new file mode 100755 index 000000000..df78983d0 --- /dev/null +++ b/projectq/ops/_qpegate_test.py @@ -0,0 +1,25 @@ +# Copyright 2017 ProjectQ-Framework (www.projectq.ch) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for projectq.ops._qpegate.""" + +from projectq.ops import _qpegate, X + + +def test_qpe_str(): + unitary = X + gate = _qpegate.QPE(unitary) + assert str(gate) == "QPE_X" + +test_qpe_str() diff --git a/projectq/setups/decompositions/phaseestimation.py b/projectq/setups/decompositions/phaseestimation.py new file mode 100644 index 000000000..c78ed972b --- /dev/null +++ b/projectq/setups/decompositions/phaseestimation.py @@ -0,0 +1,125 @@ +# Copyright 2018 ProjectQ-Framework (www.projectq.ch) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Registers a decomposition for phase estimation. + +(reference https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) + +The decomposition uses as ancillas the control qubits (qpe_ancillas) in the Command +and as system qubits (qubits) the qubits. + +The unitary operator for which the phase estimation is estimated (unitary) is teh gate +in Command + +Example: + .. code-block:: python + + n_qpe_ancillas = 5 + qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas) + system_qubits = eng.allocate_qureg(2) + U = unitary_specfic_to_the_problem() + + # Apply Quantum Phase Estimation + PhaseEstimation(unitary = U) | (qpe_ancillas, system_qubits) + + # Apply an inverse QFT and measure to the ancillas + get_inverse(QFT) | qpe_ancillas + All(Measure) | qpe_ancillas + # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) + phasebinlist = [int(q) for q in qpe_ancillas] + phase_in_bin = ''.join(str(j) for j in phasebinlist) + phase_int = int(phase_in_bin,2) + phase = phase_int / (2 ** n_qpe_ancillas) + +Attributes: + unitary (BasicGate): Unitary Operation U + +""" + +import numpy as np + +from projectq.cengines import DecompositionRule +from projectq.meta import Control, get_control_count +from projectq.ops import H, Tensor, All + +from projectq.ops import QPE + +def _decompose_QPE(cmd): + """ Decompose the Quantum Phase Estimation gate. """ + eng = cmd.engine + qpe_ancillas = cmd.qubits[0] + system_qubits = cmd.qubits[1] + unitary = cmd.gate + matrix = cmd.gate.unitary.matrix + + print (type(qpe_ancillas), len(qpe_ancillas)) + print (type(system_qubits), len(system_qubits)) + print (type(unitary)) + print (matrix) + + + """ + Initialize Phase Estimation gate. + + Apply Tensor(H) to the qpe_ancillas + + Apply the controlled-unitary gate to system_qubits in powers depending on the + numeral of the ancilla qubit (see the reference) + + Note: + The unitary must by an unitary operation + + Args: + unitary (BasicGate): unitary operation for which we want to obtain + the eigenvalues and eigenvectors + + Raises: + TypeError: If unitary is not a BasicGate + """ + + """ + BasicGate.__init__(self) + self.unitary = unitary + + qubits = self.make_tuple_of_qureg(qubits) + if len(qubits) != 2: + raise TypeError("Only two qubit or qureg are allowed.") + + # Ancillas is the first qubit/qureg. System-qubit is the second qubit/qureg + + qpe_ancillas = qubits[0] + system_qubits = qubits[1] + + # Hadamard on the ancillas + Tensor(H) | qpe_ancillas + + # Control U on the eigenvector + operator = self.unitary + + for i in range(len(qpe_ancillas)): + ipower = int(2**i) + + #for i in range(len(qpe_ancillas)): + # ipower = int(2**i) + # for j in range(ipower): + # C(operator) | (qpe_ancillas[i], system_qubits) + """ + +#: Decomposition rules +all_defined_decomposition_rules = [ + DecompositionRule(QPE, _decompose_QPE) +] + + diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py new file mode 100644 index 000000000..a51240f5a --- /dev/null +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -0,0 +1,42 @@ +# Copyright 2017 ProjectQ-Framework (www.projectq.ch) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"Tests for projectq.setups.decompositions.phaseestimation.py." + +from projectq.backends import Simulator +from projectq.cengines import (AutoReplacer, DecompositionRuleSet, + DummyEngine, InstructionFilter, MainEngine) +from projectq.meta import Control + +from projectq.ops import X, All, Measure + +from projectq.ops import QPE +from projectq.setups.decompositions import phaseestimation as pe + + +def test_phaseestimation(): + rule_set = DecompositionRuleSet(modules=[pe]) + eng = MainEngine(backend=Simulator(), + engine_list=[AutoReplacer(rule_set), + ]) + system_qubits = eng.allocate_qureg(2) + qpe_ancillas = eng.allocate_qureg(4) + eng.flush() + + U = X + + QPE(U) | (qpe_ancillas, system_qubits) + + +test_phaseestimation() From 24f47f64d7fea6bcf14296d1ce18b922cdb6ea07 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Thu, 27 Dec 2018 21:23:25 +0100 Subject: [PATCH 20/29] QPE as decomposition and gate --- docs/projectq.setups.decompositions.rst | 8 + projectq/ops/_qpegate.py | 2 +- projectq/ops/_qpegate_test.py | 2 - projectq/setups/decompositions/__init__.py | 6 +- .../setups/decompositions/phaseestimation.py | 102 +++----- .../decompositions/phaseestimation_test.py | 220 ++++++++++++++++-- 6 files changed, 256 insertions(+), 84 deletions(-) diff --git a/docs/projectq.setups.decompositions.rst b/docs/projectq.setups.decompositions.rst index 883395db6..d900f5bfc 100755 --- a/docs/projectq.setups.decompositions.rst +++ b/docs/projectq.setups.decompositions.rst @@ -26,6 +26,7 @@ The decomposition package is a collection of gate decomposition / replacement ru projectq.setups.decompositions.time_evolution projectq.setups.decompositions.toffoli2cnotandtgate projectq.setups.decompositions.uniformlycontrolledr2cnot + projectq.setups.decompositions.phaseestimation Submodules @@ -172,6 +173,13 @@ projectq.setups.decompositions.uniformlycontrolledr2cnot module :members: :undoc-members: +projectq.setups.decompositions.phaseestimation module +--------------------------------------------------------------- + +.. automodule:: projectq.setups.decompositions.phaseestimation + :members: + :undoc-members: + Module contents --------------- diff --git a/projectq/ops/_qpegate.py b/projectq/ops/_qpegate.py index 4058807ce..12701ccc7 100755 --- a/projectq/ops/_qpegate.py +++ b/projectq/ops/_qpegate.py @@ -24,6 +24,6 @@ class QPE(BasicGate): def __init__(self, unitary): BasicGate.__init__(self) self.unitary = unitary - + def __str__(self): return "QPE_"+str(self.unitary) diff --git a/projectq/ops/_qpegate_test.py b/projectq/ops/_qpegate_test.py index df78983d0..268a776fa 100755 --- a/projectq/ops/_qpegate_test.py +++ b/projectq/ops/_qpegate_test.py @@ -21,5 +21,3 @@ def test_qpe_str(): unitary = X gate = _qpegate.QPE(unitary) assert str(gate) == "QPE_X" - -test_qpe_str() diff --git a/projectq/setups/decompositions/__init__.py b/projectq/setups/decompositions/__init__.py index aab71b28c..db29dc7a8 100755 --- a/projectq/setups/decompositions/__init__.py +++ b/projectq/setups/decompositions/__init__.py @@ -31,7 +31,8 @@ swap2cnot, toffoli2cnotandtgate, time_evolution, - uniformlycontrolledr2cnot) + uniformlycontrolledr2cnot, + phaseestimation) all_defined_decomposition_rules = [ rule @@ -54,6 +55,7 @@ swap2cnot, toffoli2cnotandtgate, time_evolution, - uniformlycontrolledr2cnot] + uniformlycontrolledr2cnot, + phaseestimation] for rule in module.all_defined_decomposition_rules ] diff --git a/projectq/setups/decompositions/phaseestimation.py b/projectq/setups/decompositions/phaseestimation.py index c78ed972b..626ca7781 100644 --- a/projectq/setups/decompositions/phaseestimation.py +++ b/projectq/setups/decompositions/phaseestimation.py @@ -14,14 +14,18 @@ """ Registers a decomposition for phase estimation. - + (reference https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) -The decomposition uses as ancillas the control qubits (qpe_ancillas) in the Command -and as system qubits (qubits) the qubits. +The Quantum Phase Estimation (QPE) executes the algorithm up to the inverse +QFT included. The following steps measuring the ancillas and computing the +phase shoudl be executed outside of the QPE. + +The decomposition uses as ancillas (qpe_ancillas) the first qubit/qureg in +the Command and as system qubits teh second qubit/qureg in the Command. -The unitary operator for which the phase estimation is estimated (unitary) is teh gate -in Command +The unitary operator for which the phase estimation is estimated (unitary) +is the gate in Command Example: .. code-block:: python @@ -32,94 +36,62 @@ U = unitary_specfic_to_the_problem() # Apply Quantum Phase Estimation - PhaseEstimation(unitary = U) | (qpe_ancillas, system_qubits) + QPE(U) | (qpe_ancillas, system_qubits) - # Apply an inverse QFT and measure to the ancillas - get_inverse(QFT) | qpe_ancillas All(Measure) | qpe_ancillas - # Compute the phase from the ancilla measurement (https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) + # Compute the phase from the ancilla measurement + #(https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) phasebinlist = [int(q) for q in qpe_ancillas] phase_in_bin = ''.join(str(j) for j in phasebinlist) phase_int = int(phase_in_bin,2) phase = phase_int / (2 ** n_qpe_ancillas) Attributes: - unitary (BasicGate): Unitary Operation U + unitary (BasicGate): Unitary Operation or function to apply + on the system_qubits (e.g.: function(system_qubits, time)) """ import numpy as np from projectq.cengines import DecompositionRule -from projectq.meta import Control, get_control_count -from projectq.ops import H, Tensor, All +from projectq.meta import Control, Loop, get_control_count +from projectq.ops import H, Tensor, get_inverse, QFT from projectq.ops import QPE + def _decompose_QPE(cmd): """ Decompose the Quantum Phase Estimation gate. """ eng = cmd.engine - qpe_ancillas = cmd.qubits[0] - system_qubits = cmd.qubits[1] - unitary = cmd.gate - matrix = cmd.gate.unitary.matrix - - print (type(qpe_ancillas), len(qpe_ancillas)) - print (type(system_qubits), len(system_qubits)) - print (type(unitary)) - print (matrix) - - - """ - Initialize Phase Estimation gate. - - Apply Tensor(H) to the qpe_ancillas - - Apply the controlled-unitary gate to system_qubits in powers depending on the - numeral of the ancilla qubit (see the reference) - - Note: - The unitary must by an unitary operation - - Args: - unitary (BasicGate): unitary operation for which we want to obtain - the eigenvalues and eigenvectors - - Raises: - TypeError: If unitary is not a BasicGate - """ - - """ - BasicGate.__init__(self) - self.unitary = unitary - - qubits = self.make_tuple_of_qureg(qubits) - if len(qubits) != 2: - raise TypeError("Only two qubit or qureg are allowed.") # Ancillas is the first qubit/qureg. System-qubit is the second qubit/qureg - - qpe_ancillas = qubits[0] - system_qubits = qubits[1] + qpe_ancillas = cmd.qubits[0] + system_qubits = cmd.qubits[1] # Hadamard on the ancillas Tensor(H) | qpe_ancillas - # Control U on the eigenvector - operator = self.unitary - - for i in range(len(qpe_ancillas)): - ipower = int(2**i) - - #for i in range(len(qpe_ancillas)): - # ipower = int(2**i) - # for j in range(ipower): - # C(operator) | (qpe_ancillas[i], system_qubits) - """ + # The Unitary Operator + U = cmd.gate.unitary + + # Control U on the system_qubits + if (callable(U)): + # If U is a function + for i in range(len(qpe_ancillas)): + with Control(eng, qpe_ancillas[i]): + U(system_qubits, time=2**i) + else: + for i in range(len(qpe_ancillas)): + ipower = int(2**i) + with Loop(eng, ipower): + with Control(eng, qpe_ancillas[i]): + U | system_qubits + + # Inverse QFT on the ancillas + get_inverse(QFT) | qpe_ancillas #: Decomposition rules all_defined_decomposition_rules = [ DecompositionRule(QPE, _decompose_QPE) ] - - diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index a51240f5a..c24f69649 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -14,29 +14,221 @@ "Tests for projectq.setups.decompositions.phaseestimation.py." +import copy +import cmath +import numpy as np +import pytest + +from projectq import MainEngine from projectq.backends import Simulator from projectq.cengines import (AutoReplacer, DecompositionRuleSet, DummyEngine, InstructionFilter, MainEngine) -from projectq.meta import Control -from projectq.ops import X, All, Measure +from projectq.ops import X, H, All, Measure, Tensor, Ph + +from projectq.ops import (BasicGate) from projectq.ops import QPE from projectq.setups.decompositions import phaseestimation as pe +from projectq.setups.decompositions import qft2crandhadamard as dqft +import projectq.setups.decompositions.stateprep2cnot as stateprep2cnot +import projectq.setups.decompositions.uniformlycontrolledr2cnot as ucr2cnot + + +class PhaseX(BasicGate): + """ + A phase gate on X gate with + eigenvectors H|0> and HX|0> and + eivenvalues exp(i2pi theta) and -exp(i2pi theta) + """ + + def __init__(self, phase): + BasicGate.__init__(self) + self.phase = phase + + @property + def matrix(self): + theta = self.phase + + return np.matrix([[0, cmath.exp(1j * 2.0 * cmath.pi * theta)], + [cmath.exp(1j * 2.0 * cmath.pi * theta), 0]]) + + +class PhaseXxX(BasicGate): + """ + A phase gate on X (x) X : PhX(x)X gate with + eigenvectors: |+>|+>, |+>|->,|->|+>,|->|->, and + eivenvalues exp(i2pi theta) and -exp(i2pi theta) + """ + + def __init__(self, phase): + BasicGate.__init__(self) + self.phase = phase + + @property + def matrix(self): + theta = self.phase + + return np.matrix([[0, 0, 0, cmath.exp(1j * 2.0 * cmath.pi * theta)], + [0, 0, cmath.exp(1j * 2.0 * cmath.pi * theta), 0], + [0, cmath.exp(1j * 2.0 * cmath.pi * theta), 0, 0], + [cmath.exp(1j * 2.0 * cmath.pi * theta), 0, 0, 0]]) + + +def simple_test_X_eigenvectors(): + rule_set = DecompositionRuleSet(modules=[pe, dqft]) + eng = MainEngine(backend=Simulator(), + engine_list=[AutoReplacer(rule_set), + ]) + results = np.array([]) + for i in range(10): + autovector = eng.allocate_qureg(1) + X | autovector + H | autovector + unit = X + ancillas = eng.allocate_qureg(1) + QPE(unit) | (ancillas, autovector) + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin, 2) + phase = faseint / (2. ** (len(ancillas))) + results = np.append(results, phase) + All(Measure) | autovector + eng.flush() + + perc_95 = np.percentile(results, 95) + assert perc_95 == 0.5 + + +def test_phaseX_eigenvectors_minus(): + rule_set = DecompositionRuleSet(modules=[pe, dqft]) + eng = MainEngine(backend=Simulator(), + engine_list=[AutoReplacer(rule_set), + ]) + results = np.array([]) + for i in range(10): + autovector = eng.allocate_qureg(1) + X | autovector + H | autovector + theta = .15625 + unit = PhaseX(theta) + ancillas = eng.allocate_qureg(5) + QPE(unit) | (ancillas, autovector) + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin, 2) + phase = faseint / (2. ** (len(ancillas))) + results = np.append(results, phase) + All(Measure) | autovector + eng.flush() + + perc_75 = np.percentile(results, 75) + assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) -def test_phaseestimation(): - rule_set = DecompositionRuleSet(modules=[pe]) +def test_phaseXxX_eigenvectors_minusplus(): + rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), engine_list=[AutoReplacer(rule_set), ]) - system_qubits = eng.allocate_qureg(2) - qpe_ancillas = eng.allocate_qureg(4) - eng.flush() - - U = X - - QPE(U) | (qpe_ancillas, system_qubits) - - -test_phaseestimation() + results = np.array([]) + for i in range(10): + autovector = eng.allocate_qureg(2) + X | autovector[0] + Tensor(H) | autovector + theta = .15625 + unit = PhaseXxX(theta) + ancillas = eng.allocate_qureg(5) + QPE(unit) | (ancillas, autovector) + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin, 2) + phase = faseint / (2. ** (len(ancillas))) + results = np.append(results, phase) + All(Measure) | autovector + eng.flush() + + perc_75 = np.percentile(results, 75) + assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) + + +def test_X_no_eigenvectors(): + rule_set = DecompositionRuleSet(modules=[pe, dqft, stateprep2cnot, ucr2cnot]) + eng = MainEngine(backend=Simulator(), + engine_list=[AutoReplacer(rule_set), + ]) + results = np.array([]) + results_plus = np.array([]) + results_minus = np.array([]) + for i in range(100): + autovector = eng.allocate_qureg(1) + amplitude0 = (np.sqrt(2) + np.sqrt(6))/4. + amplitude1 = (np.sqrt(2) - np.sqrt(6))/4. + StatePreparation([amplitude0, amplitude1]) | autovector + unit = X + ancillas = eng.allocate_qureg(1) + QPE(unit) | (ancillas, autovector) + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin, 2) + phase = faseint / (2. ** (len(ancillas))) + results = np.append(results, phase) + Tensor(H) | autovector + if np.allclose(phase, .0, rtol=1e-1): + results_plus = np.append(results_plus, phase) + All(Measure) | autovector + autovector_result = int(autovector) + assert autovector_result == 0 + elif np.allclose(phase, .5, rtol=1e-1): + results_minus = np.append(results_minus, phase) + All(Measure) | autovector + autovector_result = int(autovector) + assert autovector_result == 1 + else: + All(Measure) | autovector + eng.flush() + + total = len(results_plus) + len(results_minus) + plus_probability = len(results_plus)/100. + assert total == pytest.approx(100, abs=5) + assert plus_probability == pytest.approx(1./4., abs = 1e-1), "Statistics on |+> probability are not correct (%f vs. %f)" % (plus_probability, 1./4.) + + +def test_string(): + unit = X + gate = QPE(unit) + assert (str(gate) == "QPE_X") + + +def simplefunction(system_q, time): + Ph(2.0*cmath.pi*(time + .75)) | system_q + + +def simple_test_simplefunction_eigenvectors(): + rule_set = DecompositionRuleSet(modules=[pe, dqft]) + eng = MainEngine(backend=Simulator(), + engine_list=[AutoReplacer(rule_set), + ]) + results = np.array([]) + for i in range(10): + autovector = eng.allocate_qureg(1) + ancillas = eng.allocate_qureg(2) + QPE(simplefunction) | (ancillas, autovector) + All(Measure) | ancillas + fasebinlist = [int(q) for q in ancillas] + fasebin = ''.join(str(j) for j in fasebinlist) + faseint = int(fasebin, 2) + phase = faseint / (2. ** (len(ancillas))) + results = np.append(results, phase) + All(Measure) | autovector + eng.flush() + + print(results) + perc_95 = np.percentile(results, 95) + assert perc_95 == 0.75 + +simple_test_simplefunction_eigenvectors() From 4cfc30f13d9bc41d08649185cfcf81d272a901b8 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Thu, 27 Dec 2018 21:36:14 +0100 Subject: [PATCH 21/29] QPE as decomposition and gate: correct a detail in the test --- projectq/setups/decompositions/phaseestimation_test.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index c24f69649..70b372fe3 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -230,5 +230,3 @@ def simple_test_simplefunction_eigenvectors(): print(results) perc_95 = np.percentile(results, 95) assert perc_95 == 0.75 - -simple_test_simplefunction_eigenvectors() From c6e5ebee0cfbf4bb3dfc0b26f6b3d5e11a9c6c1a Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Mon, 31 Dec 2018 12:02:12 +0100 Subject: [PATCH 22/29] try to get the travis-ci freeze solved --- projectq/setups/decompositions/phaseestimation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projectq/setups/decompositions/phaseestimation.py b/projectq/setups/decompositions/phaseestimation.py index 626ca7781..957754586 100644 --- a/projectq/setups/decompositions/phaseestimation.py +++ b/projectq/setups/decompositions/phaseestimation.py @@ -19,7 +19,7 @@ The Quantum Phase Estimation (QPE) executes the algorithm up to the inverse QFT included. The following steps measuring the ancillas and computing the -phase shoudl be executed outside of the QPE. +phase should be executed outside of the QPE. The decomposition uses as ancillas (qpe_ancillas) the first qubit/qureg in the Command and as system qubits teh second qubit/qureg in the Command. From a0727248561871efb8d5f6a229052907f24dd10d Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Mon, 31 Dec 2018 14:53:11 +0100 Subject: [PATCH 23/29] Solve a name not defined error in the phaseestimation tests --- projectq/setups/decompositions/phaseestimation_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index 70b372fe3..932f4d8c1 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -24,7 +24,7 @@ from projectq.cengines import (AutoReplacer, DecompositionRuleSet, DummyEngine, InstructionFilter, MainEngine) -from projectq.ops import X, H, All, Measure, Tensor, Ph +from projectq.ops import X, H, All, Measure, Tensor, Ph, StatePreparation from projectq.ops import (BasicGate) @@ -227,6 +227,5 @@ def simple_test_simplefunction_eigenvectors(): All(Measure) | autovector eng.flush() - print(results) perc_95 = np.percentile(results, 95) assert perc_95 == 0.75 From 53639e742245869e81cbfc575f1a5c7825682ba7 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Mon, 31 Dec 2018 15:12:00 +0100 Subject: [PATCH 24/29] Solve coverage in tests --- projectq/setups/decompositions/phaseestimation_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index 932f4d8c1..82b68510a 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -75,7 +75,7 @@ def matrix(self): [cmath.exp(1j * 2.0 * cmath.pi * theta), 0, 0, 0]]) -def simple_test_X_eigenvectors(): +def test_simple_test_X_eigenvectors(): rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), engine_list=[AutoReplacer(rule_set), @@ -208,7 +208,7 @@ def simplefunction(system_q, time): Ph(2.0*cmath.pi*(time + .75)) | system_q -def simple_test_simplefunction_eigenvectors(): +def test_simplefunction_eigenvectors(): rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), engine_list=[AutoReplacer(rule_set), From 2d20b80bc32c46d399d795d9ae70c3aefca9d31f Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sun, 20 Jan 2019 14:22:43 +0100 Subject: [PATCH 25/29] Address comments in review + change how to assert the tests --- projectq/ops/_qpegate.py | 2 +- projectq/ops/_qpegate_test.py | 2 +- .../setups/decompositions/phaseestimation.py | 8 +- .../decompositions/phaseestimation_test.py | 88 +++++-------------- 4 files changed, 31 insertions(+), 69 deletions(-) diff --git a/projectq/ops/_qpegate.py b/projectq/ops/_qpegate.py index 12701ccc7..08beee743 100755 --- a/projectq/ops/_qpegate.py +++ b/projectq/ops/_qpegate.py @@ -26,4 +26,4 @@ def __init__(self, unitary): self.unitary = unitary def __str__(self): - return "QPE_"+str(self.unitary) + return 'QPE({})'.format(str(self.unitary)) diff --git a/projectq/ops/_qpegate_test.py b/projectq/ops/_qpegate_test.py index 268a776fa..5ffcbf185 100755 --- a/projectq/ops/_qpegate_test.py +++ b/projectq/ops/_qpegate_test.py @@ -20,4 +20,4 @@ def test_qpe_str(): unitary = X gate = _qpegate.QPE(unitary) - assert str(gate) == "QPE_X" + assert str(gate) == "QPE(X)" diff --git a/projectq/setups/decompositions/phaseestimation.py b/projectq/setups/decompositions/phaseestimation.py index 957754586..7a4b8eeb8 100644 --- a/projectq/setups/decompositions/phaseestimation.py +++ b/projectq/setups/decompositions/phaseestimation.py @@ -30,10 +30,11 @@ Example: .. code-block:: python - n_qpe_ancillas = 5 + n_qpe_ancillas = 3 qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas) - system_qubits = eng.allocate_qureg(2) - U = unitary_specfic_to_the_problem() + system_qubits = eng.allocate_qureg(1) + angle = cmath.pi*2.*0.125 + U = Ph(angle) # unitary_specfic_to_the_problem() # Apply Quantum Phase Estimation QPE(U) | (qpe_ancillas, system_qubits) @@ -45,6 +46,7 @@ phase_in_bin = ''.join(str(j) for j in phasebinlist) phase_int = int(phase_in_bin,2) phase = phase_int / (2 ** n_qpe_ancillas) + print (phase) Attributes: unitary (BasicGate): Unitary Operation or function to apply diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index 82b68510a..f37829434 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -14,7 +14,6 @@ "Tests for projectq.setups.decompositions.phaseestimation.py." -import copy import cmath import numpy as np import pytest @@ -24,7 +23,7 @@ from projectq.cengines import (AutoReplacer, DecompositionRuleSet, DummyEngine, InstructionFilter, MainEngine) -from projectq.ops import X, H, All, Measure, Tensor, Ph, StatePreparation +from projectq.ops import X, H, All, Measure, Tensor, Ph, CNOT, StatePreparation from projectq.ops import (BasicGate) @@ -35,46 +34,6 @@ import projectq.setups.decompositions.uniformlycontrolledr2cnot as ucr2cnot -class PhaseX(BasicGate): - """ - A phase gate on X gate with - eigenvectors H|0> and HX|0> and - eivenvalues exp(i2pi theta) and -exp(i2pi theta) - """ - - def __init__(self, phase): - BasicGate.__init__(self) - self.phase = phase - - @property - def matrix(self): - theta = self.phase - - return np.matrix([[0, cmath.exp(1j * 2.0 * cmath.pi * theta)], - [cmath.exp(1j * 2.0 * cmath.pi * theta), 0]]) - - -class PhaseXxX(BasicGate): - """ - A phase gate on X (x) X : PhX(x)X gate with - eigenvectors: |+>|+>, |+>|->,|->|+>,|->|->, and - eivenvalues exp(i2pi theta) and -exp(i2pi theta) - """ - - def __init__(self, phase): - BasicGate.__init__(self) - self.phase = phase - - @property - def matrix(self): - theta = self.phase - - return np.matrix([[0, 0, 0, cmath.exp(1j * 2.0 * cmath.pi * theta)], - [0, 0, cmath.exp(1j * 2.0 * cmath.pi * theta), 0], - [0, cmath.exp(1j * 2.0 * cmath.pi * theta), 0, 0], - [cmath.exp(1j * 2.0 * cmath.pi * theta), 0, 0, 0]]) - - def test_simple_test_X_eigenvectors(): rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), @@ -97,11 +56,11 @@ def test_simple_test_X_eigenvectors(): All(Measure) | autovector eng.flush() - perc_95 = np.percentile(results, 95) - assert perc_95 == 0.5 + num_phase = (results == 0.5).sum() + assert num_phase/10 >= 0.4 -def test_phaseX_eigenvectors_minus(): +def test_Ph_eigenvectors(): rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), engine_list=[AutoReplacer(rule_set), @@ -109,11 +68,9 @@ def test_phaseX_eigenvectors_minus(): results = np.array([]) for i in range(10): autovector = eng.allocate_qureg(1) - X | autovector - H | autovector - theta = .15625 - unit = PhaseX(theta) - ancillas = eng.allocate_qureg(5) + theta = cmath.pi*2.*0.125 + unit = Ph(theta) + ancillas = eng.allocate_qureg(3) QPE(unit) | (ancillas, autovector) All(Measure) | ancillas fasebinlist = [int(q) for q in ancillas] @@ -124,11 +81,17 @@ def test_phaseX_eigenvectors_minus(): All(Measure) | autovector eng.flush() - perc_75 = np.percentile(results, 75) - assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) + num_phase = (results == 0.125).sum() + assert num_phase/10 >= 0.4 -def test_phaseXxX_eigenvectors_minusplus(): +def two_qubit_gate(system_q, time): + CNOT | (system_q[0], system_q[1]) + Ph(2.0*cmath.pi*(time * .125)) | system_q[1] + CNOT | (system_q[0], system_q[1]) + + +def test_2qubitsPh_eigenvectors(): rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), engine_list=[AutoReplacer(rule_set), @@ -137,11 +100,8 @@ def test_phaseXxX_eigenvectors_minusplus(): for i in range(10): autovector = eng.allocate_qureg(2) X | autovector[0] - Tensor(H) | autovector - theta = .15625 - unit = PhaseXxX(theta) - ancillas = eng.allocate_qureg(5) - QPE(unit) | (ancillas, autovector) + ancillas = eng.allocate_qureg(3) + QPE(two_qubit_gate) | (ancillas, autovector) All(Measure) | ancillas fasebinlist = [int(q) for q in ancillas] fasebin = ''.join(str(j) for j in fasebinlist) @@ -151,8 +111,8 @@ def test_phaseXxX_eigenvectors_minusplus(): All(Measure) | autovector eng.flush() - perc_75 = np.percentile(results, 75) - assert perc_75 == pytest.approx(.65625, abs=1e-2), "Percentile 75 not as expected (%f)" % (perc_75) + num_phase = (results == .125).sum() + assert num_phase/10 >= 0.4 def test_X_no_eigenvectors(): @@ -201,11 +161,11 @@ def test_X_no_eigenvectors(): def test_string(): unit = X gate = QPE(unit) - assert (str(gate) == "QPE_X") + assert (str(gate) == "QPE(X)") def simplefunction(system_q, time): - Ph(2.0*cmath.pi*(time + .75)) | system_q + Ph(2.0*cmath.pi*(time * .75)) | system_q def test_simplefunction_eigenvectors(): @@ -227,5 +187,5 @@ def test_simplefunction_eigenvectors(): All(Measure) | autovector eng.flush() - perc_95 = np.percentile(results, 95) - assert perc_95 == 0.75 + num_phase = (results == .75).sum() + assert num_phase/10 >= 0.4 From a676d2942c90f4228c3ab0ec0b9865121818f099 Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sun, 20 Jan 2019 17:41:08 +0100 Subject: [PATCH 26/29] Enhance statistis in the tests bi more executions --- .../decompositions/phaseestimation_test.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index f37829434..a8820974f 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -40,7 +40,7 @@ def test_simple_test_X_eigenvectors(): engine_list=[AutoReplacer(rule_set), ]) results = np.array([]) - for i in range(10): + for i in range(100): autovector = eng.allocate_qureg(1) X | autovector H | autovector @@ -57,7 +57,7 @@ def test_simple_test_X_eigenvectors(): eng.flush() num_phase = (results == 0.5).sum() - assert num_phase/10 >= 0.4 + assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) def test_Ph_eigenvectors(): @@ -66,7 +66,7 @@ def test_Ph_eigenvectors(): engine_list=[AutoReplacer(rule_set), ]) results = np.array([]) - for i in range(10): + for i in range(100): autovector = eng.allocate_qureg(1) theta = cmath.pi*2.*0.125 unit = Ph(theta) @@ -82,7 +82,7 @@ def test_Ph_eigenvectors(): eng.flush() num_phase = (results == 0.125).sum() - assert num_phase/10 >= 0.4 + assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) def two_qubit_gate(system_q, time): @@ -97,7 +97,7 @@ def test_2qubitsPh_eigenvectors(): engine_list=[AutoReplacer(rule_set), ]) results = np.array([]) - for i in range(10): + for i in range(100): autovector = eng.allocate_qureg(2) X | autovector[0] ancillas = eng.allocate_qureg(3) @@ -112,7 +112,7 @@ def test_2qubitsPh_eigenvectors(): eng.flush() num_phase = (results == .125).sum() - assert num_phase/10 >= 0.4 + assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) def test_X_no_eigenvectors(): @@ -174,7 +174,7 @@ def test_simplefunction_eigenvectors(): engine_list=[AutoReplacer(rule_set), ]) results = np.array([]) - for i in range(10): + for i in range(100): autovector = eng.allocate_qureg(1) ancillas = eng.allocate_qureg(2) QPE(simplefunction) | (ancillas, autovector) @@ -188,4 +188,4 @@ def test_simplefunction_eigenvectors(): eng.flush() num_phase = (results == .75).sum() - assert num_phase/10 >= 0.4 + assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) From 393c8f1ae4c0e157d67e4c7d3e3542d94866c72c Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Mon, 21 Jan 2019 22:00:03 +0100 Subject: [PATCH 27/29] Correct bad calculation in tests --- .../decompositions/phaseestimation_test.py | 39 +++---------------- 1 file changed, 6 insertions(+), 33 deletions(-) diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index a8820974f..208e6b1bc 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -57,7 +57,7 @@ def test_simple_test_X_eigenvectors(): eng.flush() num_phase = (results == 0.5).sum() - assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) + assert num_phase/100. >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.4) def test_Ph_eigenvectors(): @@ -82,16 +82,16 @@ def test_Ph_eigenvectors(): eng.flush() num_phase = (results == 0.125).sum() - assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) + assert num_phase/100. >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.4) def two_qubit_gate(system_q, time): CNOT | (system_q[0], system_q[1]) - Ph(2.0*cmath.pi*(time * .125)) | system_q[1] + Ph(2.0*cmath.pi*(time * 0.125)) | system_q[1] CNOT | (system_q[0], system_q[1]) -def test_2qubitsPh_eigenvectors(): +def test_2qubitsPh_andfunction_eigenvectors(): rule_set = DecompositionRuleSet(modules=[pe, dqft]) eng = MainEngine(backend=Simulator(), engine_list=[AutoReplacer(rule_set), @@ -111,8 +111,8 @@ def test_2qubitsPh_eigenvectors(): All(Measure) | autovector eng.flush() - num_phase = (results == .125).sum() - assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) + num_phase = (results == 0.125).sum() + assert num_phase/100. >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.4) def test_X_no_eigenvectors(): @@ -162,30 +162,3 @@ def test_string(): unit = X gate = QPE(unit) assert (str(gate) == "QPE(X)") - - -def simplefunction(system_q, time): - Ph(2.0*cmath.pi*(time * .75)) | system_q - - -def test_simplefunction_eigenvectors(): - rule_set = DecompositionRuleSet(modules=[pe, dqft]) - eng = MainEngine(backend=Simulator(), - engine_list=[AutoReplacer(rule_set), - ]) - results = np.array([]) - for i in range(100): - autovector = eng.allocate_qureg(1) - ancillas = eng.allocate_qureg(2) - QPE(simplefunction) | (ancillas, autovector) - All(Measure) | ancillas - fasebinlist = [int(q) for q in ancillas] - fasebin = ''.join(str(j) for j in fasebinlist) - faseint = int(fasebin, 2) - phase = faseint / (2. ** (len(ancillas))) - results = np.append(results, phase) - All(Measure) | autovector - eng.flush() - - num_phase = (results == .75).sum() - assert num_phase/10 >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/10, 0.4) From 016248dac08c5f01533b6756f571da176a28245d Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Mon, 21 Jan 2019 22:10:48 +0100 Subject: [PATCH 28/29] Refine test --- projectq/setups/decompositions/phaseestimation_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index 208e6b1bc..7e3adca3a 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -57,7 +57,7 @@ def test_simple_test_X_eigenvectors(): eng.flush() num_phase = (results == 0.5).sum() - assert num_phase/100. >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.4) + assert num_phase/100. >= 0.35, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.35) def test_Ph_eigenvectors(): @@ -82,7 +82,7 @@ def test_Ph_eigenvectors(): eng.flush() num_phase = (results == 0.125).sum() - assert num_phase/100. >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.4) + assert num_phase/100. >= 0.35, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.35) def two_qubit_gate(system_q, time): @@ -112,7 +112,7 @@ def test_2qubitsPh_andfunction_eigenvectors(): eng.flush() num_phase = (results == 0.125).sum() - assert num_phase/100. >= 0.4, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.4) + assert num_phase/100. >= 0.35, "Statistics phase calculation are not correct (%f vs. %f)" % (num_phase/100., 0.35) def test_X_no_eigenvectors(): From 867fecbd6b290f75c210be2cf58182ee08d302bb Mon Sep 17 00:00:00 2001 From: Fernando de la Iglesia Date: Sun, 21 Apr 2019 14:44:55 +0200 Subject: [PATCH 29/29] Address Andi comments: add detail in the examples and atributes and removing code in the test that is never executed --- .../setups/decompositions/phaseestimation.py | 34 +++++++++++++++++-- .../decompositions/phaseestimation_test.py | 2 -- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/projectq/setups/decompositions/phaseestimation.py b/projectq/setups/decompositions/phaseestimation.py index 7a4b8eeb8..faf7523cf 100644 --- a/projectq/setups/decompositions/phaseestimation.py +++ b/projectq/setups/decompositions/phaseestimation.py @@ -30,6 +30,8 @@ Example: .. code-block:: python + # Example using a ProjectQ gate + n_qpe_ancillas = 3 qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas) system_qubits = eng.allocate_qureg(1) @@ -48,9 +50,37 @@ phase = phase_int / (2 ** n_qpe_ancillas) print (phase) + # Example using a function (two_qubit_gate). + # Instead of applying QPE on a gate U one could provide a function + + def two_qubit_gate(system_q, time): + CNOT | (system_q[0], system_q[1]) + Ph(2.0*cmath.pi*(time * 0.125)) | system_q[1] + CNOT | (system_q[0], system_q[1]) + + n_qpe_ancillas = 3 + qpe_ancillas = eng.allocate_qureg(n_qpe_ancillas) + system_qubits = eng.allocate_qureg(2) + X | system_qubits[0] + + # Apply Quantum Phase Estimation + QPE(two_qubit_gate) | (qpe_ancillas, system_qubits) + + All(Measure) | qpe_ancillas + # Compute the phase from the ancilla measurement + #(https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm) + phasebinlist = [int(q) for q in qpe_ancillas] + phase_in_bin = ''.join(str(j) for j in phasebinlist) + phase_int = int(phase_in_bin,2) + phase = phase_int / (2 ** n_qpe_ancillas) + print (phase) + Attributes: - unitary (BasicGate): Unitary Operation or function to apply - on the system_qubits (e.g.: function(system_qubits, time)) + unitary (BasicGate): Unitary Operation either a ProjectQ gate or a function f. + Calling the function with the parameters system_qubits(Qureg) and time (integer), + i.e. f(system_qubits, time), applies to the system qubits a unitary defined in f + with parameter time. + """ diff --git a/projectq/setups/decompositions/phaseestimation_test.py b/projectq/setups/decompositions/phaseestimation_test.py index 7e3adca3a..828e522a4 100644 --- a/projectq/setups/decompositions/phaseestimation_test.py +++ b/projectq/setups/decompositions/phaseestimation_test.py @@ -148,8 +148,6 @@ def test_X_no_eigenvectors(): All(Measure) | autovector autovector_result = int(autovector) assert autovector_result == 1 - else: - All(Measure) | autovector eng.flush() total = len(results_plus) + len(results_minus)