#lang scribble/base @(require scribble/manual) @title{Qlambda: A lambda calculus for computation} @section{Information} This package includes the quantum algorithms in the paper "A lambda calculus for quantum computation". However, in this version linearity assumptions are left implicit, and it is up to the programmer to correctly use linear arguments. Failing to do so may result in nonsensical results. Copyright 2003 - Andre van Tonder Translated in to scribble by Joshua Jay Herman @section{Preliminaries} First let's apply a few Hadamard gates in sequence to a single qubit: @schemeblock[(qeval (H (H (H 0))))] @verbatim|{ => (superposition (0.7071067811865 1) (0.7071067811865 0)) }| @schemeblock[(qeval (H (H (H (H 0)))))] @verbatim|{ ; => (superposition (1.0 0)) }| @section{Make an EPR State} Let's define a function that makes an EPR state: @schemeblock[(define (make-epr) (cnot (H 0) 0))] @schemeblock[(qeval (make-epr))] @verbatim|{ => (superposition (0.7071067811865 (1 1)) (0.7071067811865 (0 0))) }| @section{Deutsch Algorithm} The Deutsch algorithm is easily defined: Here Uf is the oracle corresponding to an unknown function f : Bit -> Bit. Note that all variables appear linearly. @schemeblock[(define (deutsch Uf) (bind* ([x (H 0)] [y (H 1)] [(x* y*) (Uf x y)]) (list (H x*) (H y*)))) ] For example, Uf = cnot corresponds to f(0) = 0, f(1) = 1: @schemeblock[ (qeval (deutsch cnot))] @verbatim|{ => (superposition (1.0 (1 1))) }| The first qubit is indeed 1 = f(0) + f(1) mod 2. Another example, Uf = @schemeblock[(lambda (x y) (list x y))] corresponds to f(0) = f(1) = 0: @schemeblock[ (qeval (deutsch (lambda (x y) (list x y)))) ] @verbatim|{ => (superposition (1.0 (0 1)))}| The first qubit is indeed 0 = f(0) + f(1) mod 2. @section{ Quantum teleportation) Once again all variables appear linearly.} @schemeblock[ (define (teleport x) (bind* ([(e1 e2) (make-epr)] [(x* e1*) (alice x e1)]) (bob x* e1* e2))) (define (alice x e) (bind ([(x* e*) (cnot x e)]) (list (H x*) e*))) (define (bob x e1 e2) (bind* ([(e1* e2*) (cX e1 e2)] [(x* e2**) (cZ x e2*)]) (list x* e1* e2**))) ] Let's teleport a qubit in the state (|0> - |1>)/sqrt(2): @schemeblock[(qeval (teleport (H 1)))] @verbatim|{ => (superposition (-0.3535533905933 (1 0 1)) (-0.3535533905933 (0 0 1)) (-0.3535533905933 (1 1 1)) (-0.3535533905933 (0 1 1)) (0.3535533905933 (1 1 0)) (0.3535533905933 (0 1 0)) (0.3535533905933 (1 0 0)) (0.3535533905933 (0 0 0))) }| Ignoring the first two bits, the third bit, belonging to Bob, is now in the state (|0> - |1>)/sqrt(2) @section{ Creating a uniform superposition} @schemeblock[(qeval (map (!suspend H) '(0 0 0)))] @verbatim|{ => (superposition (0.3535533905933 (1 1 1)) (0.3535533905933 (1 1 0)) (0.3535533905933 (1 0 1)) (0.3535533905933 (1 0 0)) (0.3535533905933 (0 1 1)) (0.3535533905933 (0 1 0)) (0.3535533905933 (0 0 1)) }| @section{Quantum Fourier transform:} @schemeblock[ (define (fourier lst) (reverse (fourier* lst))) (define (fourier* lst) (list-match lst [() '()] [(hd . tl) (bind ([(hd* . tl*) (phases (H hd) tl 2)]) (cons hd* (fourier* tl*)))])) (define (phases target controls n) (list-match controls [() (list target)] [(control . tl) (bind* ([(control* target*) ((cR n) control target)] [(target** . tl*) (phases target* tl (add1 n))]) (cons target** (cons control* tl*)))])) ] @section{Testing the Fourier transform} @schemeblock[(qeval (fourier '(1 0)))] @verbatim|{ => (superposition (-0.5 (1 1)) (-0.5 (0 1)) (0.5 (1 0)) (0.5 (0 0))) }| @schemeblock[(qeval (fourier '(1 1 1)))] @verbatim|{ => (superposition (0.25+0.25i (1 1 1)) (-0.25-0.25i (0 1 1)) (-0.25+0.25i (1 0 1)) (0.25-0.25i (0 0 1)) (0.0+0.3535533905933i (1 1 0)) (-0.0-0.3535533905933i (0 1 0)) (-0.3535533905933 (1 0 0)) (0.3535533905933 (0 0 0))) }|