quipper-demos (empty) → 0.9.0.0
raw patch · 173 files changed
+7576/−0 lines, 173 filesdep +basedep +containersdep +newsynthbuild-type:Customsetup-changedbinary-added
Dependencies added: base, containers, newsynth, quipper-language, quipper-libraries, quipper-utils, random
Files
- COPYRIGHT +66/−0
- ChangeLog +76/−0
- Quipper/Algorithms/BWT/Alternative.hs +755/−0
- Quipper/Algorithms/BWT/BWT.hs +600/−0
- Quipper/Algorithms/BWT/Definitions.hs +35/−0
- Quipper/Demos/And_gate.hs +10/−0
- Quipper/Demos/And_list.hs +20/−0
- Quipper/Demos/And_rev.hs +26/−0
- Quipper/Demos/Arith.hs +13/−0
- Quipper/Demos/Box.hs +112/−0
- Quipper/Demos/BoxExample.hs +36/−0
- Quipper/Demos/Classical.hs +12/−0
- Quipper/Demos/Comments.hs +25/−0
- Quipper/Demos/CountAccess.hs +63/−0
- Quipper/Demos/Decompose_test.hs +23/−0
- Quipper/Demos/DynamicLifting.hs +23/−0
- Quipper/Demos/ErrorCircuit.hs +28/−0
- Quipper/Demos/Example.hs +37/−0
- Quipper/Demos/Example1.hs +10/−0
- Quipper/Demos/Example2.hs +12/−0
- Quipper/Demos/Example3.hs +21/−0
- Quipper/Demos/Example4.hs +11/−0
- Quipper/Demos/GPhase.hs +33/−0
- Quipper/Demos/HelloWorld.hs +11/−0
- Quipper/Demos/Infinite.hs +26/−0
- Quipper/Demos/MultiControlledNot.hs +30/−0
- Quipper/Demos/NBox.hs +22/−0
- Quipper/Demos/NamedGate.hs +30/−0
- Quipper/Demos/NoControl.hs +74/−0
- Quipper/Demos/OptimTest.hs +53/−0
- Quipper/Demos/ParseNodeRoot.hs +39/−0
- Quipper/Demos/PhaseTest.hs +22/−0
- Quipper/Demos/QEC.hs +139/−0
- Quipper/Demos/QFT.hs +5/−0
- Quipper/Demos/QFTAdder.hs +64/−0
- Quipper/Demos/QRAM.hs +15/−0
- Quipper/Demos/QuantumIfTest.hs +125/−0
- Quipper/Demos/Reverse.hs +13/−0
- Quipper/Demos/SimpleOracleSimulation.hs +85/−0
- Quipper/Demos/SimulationTest.hs +30/−0
- Quipper/Demos/SynthesisTest.hs +106/−0
- Quipper/Demos/Teleport.hs +55/−0
- Quipper/Demos/TeleportGeneric.hs +170/−0
- Quipper/Demos/TemplateTest.hs +67/−0
- Quipper/Demos/Test.hs +31/−0
- Quipper/Demos/Testing.hs +79/−0
- Quipper/Demos/TimeStep-binary.hs +36/−0
- Quipper/Demos/TimeStep.hs +34/−0
- Quipper/Demos/TransformerExample.hs +23/−0
- Quipper/Demos/WithComputed.hs +40/−0
- Setup.hs +15/−0
- dist/build/And_gate/And_gate-tmp/Quipper/Demos/And_gate.hs +14/−0
- dist/build/And_list/And_list-tmp/Quipper/Demos/And_list.hs +24/−0
- dist/build/And_rev/And_rev-tmp/Quipper/Demos/And_rev.hs +30/−0
- dist/build/Arith/Arith-tmp/Quipper/Demos/Arith.hs +17/−0
- dist/build/Box/Box-tmp/Quipper/Demos/Box.hs +116/−0
- dist/build/BoxExample/BoxExample-tmp/Quipper/Demos/BoxExample.hs +40/−0
- dist/build/Classical/Classical-tmp/Quipper/Demos/Classical.hs +16/−0
- dist/build/Comments/Comments-tmp/Quipper/Demos/Comments.hs +29/−0
- dist/build/CountAccess/CountAccess-tmp/Quipper/Demos/CountAccess.hs +67/−0
- dist/build/Decompose_test/Decompose_test-tmp/Quipper/Demos/Decompose_test.hs +27/−0
- dist/build/DynamicLifting/DynamicLifting-tmp/Quipper/Demos/DynamicLifting.hs +27/−0
- dist/build/ErrorCircuit/ErrorCircuit-tmp/Quipper/Demos/ErrorCircuit.hs +32/−0
- dist/build/Example/Example-tmp/Quipper/Demos/Example.hs +41/−0
- dist/build/Example1/Example1-tmp/Quipper/Demos/Example1.hs +14/−0
- dist/build/Example2/Example2-tmp/Quipper/Demos/Example2.hs +16/−0
- dist/build/Example3/Example3-tmp/Quipper/Demos/Example3.hs +25/−0
- dist/build/Example4/Example4-tmp/Quipper/Demos/Example4.hs +15/−0
- dist/build/GPhase/GPhase-tmp/Quipper/Demos/GPhase.hs +37/−0
- dist/build/HelloWorld/HelloWorld-tmp/Quipper/Demos/HelloWorld.hs +15/−0
- dist/build/Infinite/Infinite-tmp/Quipper/Demos/Infinite.hs +30/−0
- dist/build/MultiControlledNot/MultiControlledNot-tmp/Quipper/Demos/MultiControlledNot.hs +34/−0
- dist/build/NBox/NBox-tmp/Quipper/Demos/NBox.hs +26/−0
- dist/build/NamedGate/NamedGate-tmp/Quipper/Demos/NamedGate.hs +34/−0
- dist/build/NoControl/NoControl-tmp/Quipper/Demos/NoControl.hs +78/−0
- dist/build/OptimTest/OptimTest-tmp/Quipper/Demos/OptimTest.hs +86/−0
- dist/build/ParseNodeRoot/ParseNodeRoot-tmp/Quipper/Demos/ParseNodeRoot.hs +43/−0
- dist/build/PhaseTest/PhaseTest-tmp/Quipper/Demos/PhaseTest.hs +26/−0
- dist/build/QEC/QEC-tmp/Quipper/Demos/QEC.hs +143/−0
- dist/build/QFT/QFT-tmp/Quipper/Demos/QFT.hs +9/−0
- dist/build/QFTAdder/QFTAdder-tmp/Quipper/Demos/QFTAdder.hs +68/−0
- dist/build/QRAM/QRAM-tmp/Quipper/Demos/QRAM.hs +19/−0
- dist/build/QuantumIfTest/QuantumIfTest-tmp/Quipper/Demos/QuantumIfTest.hs +129/−0
- dist/build/Reverse/Reverse-tmp/Quipper/Demos/Reverse.hs +17/−0
- dist/build/SimpleOracleSimulation/SimpleOracleSimulation-tmp/Quipper/Algorithms/BWT/Alternative.hs +759/−0
- dist/build/SimpleOracleSimulation/SimpleOracleSimulation-tmp/Quipper/Algorithms/BWT/BWT.hs +604/−0
- dist/build/SimpleOracleSimulation/SimpleOracleSimulation-tmp/Quipper/Algorithms/BWT/Definitions.hs +39/−0
- dist/build/SimpleOracleSimulation/SimpleOracleSimulation-tmp/Quipper/Demos/SimpleOracleSimulation.hs +89/−0
- dist/build/SimulationTest/SimulationTest-tmp/Quipper/Demos/SimulationTest.hs +34/−0
- dist/build/SynthesisTest/SynthesisTest-tmp/Quipper/Demos/SynthesisTest.hs +110/−0
- dist/build/Teleport/Teleport-tmp/Quipper/Demos/Teleport.hs +59/−0
- dist/build/TeleportGeneric/TeleportGeneric-tmp/Quipper/Demos/TeleportGeneric.hs +174/−0
- dist/build/TemplateTest/TemplateTest-tmp/Quipper/Demos/TemplateTest.hs +95/−0
- dist/build/Test/Test-tmp/Quipper/Demos/Test.hs +35/−0
- dist/build/Testing/Testing-tmp/Quipper/Demos/Testing.hs +83/−0
- dist/build/TimeStep-binary/TimeStep-binary-tmp/Quipper/Algorithms/BWT/Definitions.hs +39/−0
- dist/build/TimeStep-binary/TimeStep-binary-tmp/Quipper/Demos/TimeStep-binary.hs +40/−0
- dist/build/TimeStep/TimeStep-tmp/Quipper/Algorithms/BWT/Definitions.hs +39/−0
- dist/build/TimeStep/TimeStep-tmp/Quipper/Demos/TimeStep.hs +38/−0
- dist/build/TransformerExample/TransformerExample-tmp/Quipper/Demos/TransformerExample.hs +27/−0
- dist/build/WithComputed/WithComputed-tmp/Quipper/Demos/WithComputed.hs +44/−0
- images/CosetState.png binary
- images/E.png binary
- images/ERot_phase.png binary
- images/ERot_zx.png binary
- images/G.png binary
- images/GateR.png binary
- images/Rz.png binary
- images/T.png binary
- images/V.png binary
- images/W.png binary
- images/Y.png binary
- images/adder-optimized.png binary
- images/adder-unoptimized.png binary
- images/b0-template.png binary
- images/b1-template.png binary
- images/b2-orthodox.png binary
- images/b2-template.png binary
- images/b3-template.png binary
- images/b4-template.png binary
- images/cH_AMMR.png binary
- images/ccZ_AMMR.png binary
- images/ccZ_S.png binary
- images/cc_iX.png binary
- images/cc_iX_S.png binary
- images/cc_iX_simple.png binary
- images/contfrac.png binary
- images/controlled-phase-decomp.png binary
- images/controlled-zrot.png binary
- images/controlled_E.png binary
- images/controlled_S.png binary
- images/controlled_T.png binary
- images/controlled_V.png binary
- images/controlled_W.png binary
- images/controlled_YY.png binary
- images/controlled_iX.png binary
- images/controlled_phase.png binary
- images/coord.png binary
- images/dashed-cnot-bwd.png binary
- images/dashed-cnot-fwd.png binary
- images/decompose2Controls.png binary
- images/decomposeControls.png binary
- images/def_f.png binary
- images/def_g.png binary
- images/def_g1.png binary
- images/def_h.png binary
- images/expDA.png binary
- images/floor.png binary
- images/floor2.png binary
- images/fredkin.png binary
- images/gate_W_CliffordT.png binary
- images/hex-coord.png binary
- images/hex1.png binary
- images/hex2.png binary
- images/iX.png binary
- images/multi_ciX_noancilla.png binary
- images/multi_cnot_barenco.png binary
- images/phase.png binary
- images/quantum_and.png binary
- images/quantum_and_iX.png binary
- images/rGate.png binary
- images/spin1.png binary
- images/spin2.png binary
- images/toffoli_AMMR.png binary
- images/toffoli_NC.png binary
- images/toffoli_S.png binary
- images/toffoli_V.png binary
- images/weldedtree.png binary
- images/with_combined_controls1.png binary
- images/with_combined_controls2.png binary
- images/with_computed.png binary
- images/with_signed_qubit.png binary
- quipper-demos.cabal +438/−0
@@ -0,0 +1,66 @@+Contributors are listed here, in alphabetical order by last name.+Unless otherwise noted, the copyright for his or her contributions+rests with each individual author. For contributions by authors whose+name is marked (ACS), the copyright rests with Applied Communication+Sciences.++Copyright (C) 2011-2019. All rights reserved.+Copyright (C) 2012-2013 Applied Communication Sciences. All rights+reserved.++Richard Eisenberg+Alexander S. Green+Peter LeFanu Lumsdaine+Keith Kim (ACS)+Siun-Chuon Mau (ACS)+Baranidharan Mohan+Won Ng (ACS)+Joel Ravelomanantsoa-Ratsimihah+Neil J. Ross+Artur Scherer (ACS)+Peter Selinger+Benoît Valiron+Alexandr Virodov (ACS)+Stephan A. Zdancewic++This research was supported by the Intelligence Advanced Research+Projects Activity (IARPA) via Department of Interior National Business+Center contract numbers D11PC20168 and D12PC00527. The U.S. Government+is authorized to reproduce and distribute reprints for Governmental+purposes notwithstanding any copyright annotation thereon. Disclaimer:+The views and conclusions contained herein are those of the authors+and should not be interpreted as necessarily representing the official+policies or endorsements, either expressed or implied, of IARPA,+DoI/NBC, or the U.S. Government.++----------------------------------------------------------------------+LICENSE++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the+ distribution.++3. The name of the authors and copyright holders may not be used to+ endorse or promote products derived from this software without+ specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.+----------------------------------------------------------------------
@@ -0,0 +1,76 @@+December 29, 2019: Release 0.9.0.0++ * Overhauled module structure:+ + Old: New:+ ==== ====+ + Quipper.XYZ Quipper.Internal.XYZ+ QuipperLib.XYZ Quipper.Libraries.XYZ+ Libraries.XYZ Quipper.Utils.XYZ+ Algorithms.XYZ Quipper.Algorithms.XYZ+ tests Quipper.Demos+ Programs Quipper.Programs++ * Re-packaged Quipper as Cabal packages. Added executables quipper,+ quipper-pp, quipperi, quipperdoc in lieu of shell scripts.+ * Moved PDF Previewer to a separate library in Quipper.Utils.Preview+ * Added a MonadFail instance to Circ, to keep ghc >= 7.4 happy+ * Use type class synonyms to avoid warnings about simplifiable class.+ * Compatibility: removed obsolete functoin Map.insertWith'.+ * Added MultiControlledNot demo.+ * Removed dependency on set-monad, which is broken upstream.+ * Fixed some bugs in the stabilizer simulation.+ * Moved QuantumIf from BF to Libraries.+ * Added --help option to all Quipper tools.+ * Removed Quipper.Utils.ShowAll+ * Fixed some compiler errors and removed some unnecessary type class+ assumptions.++July 27, 2016: Release 0.8++ * Portability: compatibility fixes for GHC 8.0. Note: GHC 7.10 is too+ broken and will not be supported by Quipper.+ * Added tests/SimulationTest+ * Added QPrep and QUnPrep to the simulator++October 14, 2014: Release 0.7++ * Portability: compatibility fixes for GHC 7.8.++January 16, 2014: Release 0.6++ * Minor edits and documentation updates.+ * Added a new gate gate_iX_inv+ * Added "alternate" version of synthesis algorithm, using only+ generators of determinant 1 if possible.+ * Synthesis code is now in an external package "newsynth".+ * Rendering code is now in an external package "easyrender".+ * Updated for use with fixedprec-0.2.1.0.++September 2, 2013: Release 0.5++ * Portability: compatibility fixes for GHC 7.6.2.+ * Portability: fixed Windows incompatibility bug. Handling of Ctrl-C+ may or may not work on Windows, depending on console.+ * Added quipperi script, analogous to ghci.+ * New library QuipperLib.ClassicalOptim: algebraic optimization of+ auto-generated classical circuits. Added "optimized" oracle to BWT+ algorithm.+ * QuipperLib.Decompose: Added decomposition into a "standard" gate+ set, consisting of X, Y, Z, H, S, S-dagger, T, T-dagger, and CNOT.+ Added KeepPhase flag to some transformers.+ * QuipperLib.GateDecompositions: added more gates.+ * New library Libraries.Synthesis.RotationDecomposition: implements a+ variant of the algorithm from Nielsen and Chuang to decompose an+ nxn unitary operator into one- and two-level rotations.+ * New library QuipperLib.Unboxing: unboxing transformers.+ * Updated ASCII output format; improved circuit parser efficiency.+ * Miscellaneous bug fixes: malformed W-gates, qdata_of_qubits,+ floorlog.+ * Fixed handling of iterated subroutines in depth transformer.+ * Documentation updates and minor refactoring.++June 19, 2013: Release 0.4++ * First public release.
@@ -0,0 +1,755 @@+{-# LANGUAGE FlexibleContexts #-}++-- | Alternative implementations for the binary welded tree algorithm.+-- The purpose of these is to experiment with and potentially+-- illustrate a more functional programming style.++module Quipper.Algorithms.BWT.Alternative where++import Quipper++import Quipper.Libraries.Qureg+import Quipper.Libraries.Simulation++import Quipper.Algorithms.BWT.Definitions++-- import other Quipper stuff+import qualified Quipper.Algorithms.BWT.BWT as BWT++import Quipper.Utils.Sampling+import Quipper.Utils.Auxiliary++-- import other stuff+import Control.Monad+import Text.Printf+import Data.Bits (xor)+import Text.Printf++import Data.Map (Map)+import qualified Data.Map as Map+++-- ======================================================================+-- * Oracle abstraction++-- | This is a version of 'BWT.Oracle' that uses 'Qulist' instead of+-- 'Qureg'. An oracle provides the following information: the tree+-- depth /n/, the label length /m/, the number of edge colors /k/,+-- the entrance label /ENTRANCE/, and for each color 0 ≤ /c/ < /k/,+-- a reversible circuit /ORACLE[sub c](a,b,r)/.++data Oracle = Oracle {+ n :: Int,+ m :: Int,+ k :: Int,+ entrance :: Boollist,+ oraclefun :: Int -> (Qulist, Qulist, Qubit) -> Circ ()+}++-- | Convert a "Alternative".'Oracle' into a "BWT".'BWT.Oracle'.+convert_oracle :: Oracle -> BWT.Oracle+convert_oracle Oracle { n=n, m=m, k=k, entrance=e, oraclefun=f1 } =+ BWT.Oracle { BWT.n=n, BWT.m=m, BWT.k=k, BWT.entrance=e, BWT.oraclefun=f2 } + where + f2 c (a, b, r) = f1 c (qulist_of_qureg_te a, qulist_of_qureg_te b, r)++-- ======================================================================+-- * Top-level algorithm++-- | Do a quantum random walk on the binary welded tree given by the+-- oracle, for /s/ times steps of length /dt/. Return a bit list+-- corresponding to the probable exit label. This is a more+-- functional implementation of 'BWT.qrwbwt' from the module "BWT".+-- +-- Note: This implementation does not rely on the oracle being+-- self-inverse, and therefore only requires that+-- +-- > ORACLE[sub c](a, 0, 0) = (a, v[sub c](a), f[sub c](a)), +-- +-- rather than the more general property +-- +-- > ORACLE[sub c](a, b, r) = (a, b ⊕ v[sub c](a), r ⊕ f[sub c](a)). +-- +-- This gives us the freedom to build more efficient oracles, where+-- appropriate.+qrwbwt :: Oracle -> Timestep -> Int -> Circ Bitlist+qrwbwt oracle dt s = do+ comment (printf "ENTER: qrwbwt (dt=%.3e, s=%d)" dt s)+ -- Initialize a to the entrance label.+ a <- qinit (entrance oracle)++ -- Run the Hamiltonian /s/ times for time step /dt/.+ replicateM s $ hamiltonian dt oracle a++ -- Measure /a/.+ exit <- measure a+ comment_with_label "EXIT: qrwbwt" exit "exit"+ return exit++-- | Apply one round of the Hamiltonian for time step /dt/ to /a/.+hamiltonian :: Timestep -> Oracle -> Qulist -> Circ ()+hamiltonian dt oracle a = do+ comment_with_label "ENTER: hamiltonian" a "a"+ for 0 ((k oracle)-1) 1 $ \c -> do+ -- for c from 0 to k-1++ -- create ancillas b and r+ with_ancilla_list (length a) $ \b -> do+ with_ancilla $ \r -> do++ -- perform computations+ (oraclefun oracle) c (a,b,r)+ time_step dt (a,b,r)+ reverse_generic_imp ((oraclefun oracle) c) (a,b,r)+ -- "reverse" here is not quite GFI+ comment_with_label "EXIT: hamiltonian" a "a"++-- | Apply the diffusion step to /(a,b,r)/. Here /a/ and /b/ must be+-- of equal length.+time_step :: Timestep -> (Qulist, Qulist, Qubit) -> Circ ()+time_step dt (a,b,r) = do+ comment_with_label "ENTER: time_step" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ basischange (a,b,h)+ controlledExpGate (dt,r,h)+ (reverse_generic_imp basischange) (a,b,h)+ comment_with_label "EXIT: time_step" (a,b,r) ("a","b","r")++-- | Apply the basis change from Figure 3 of \[Childs et al.\] to /a/,+-- /b/, and /h/. Here /a/ and /b/ must be of equal length.+basischange :: (Qulist, Qulist, Qubit) -> Circ ()+basischange (a,b,h) = do+ comment_with_label "ENTER: basischange" (a,b,h) ("a","b","h")+ -- apply W gates+ zipWithM_ gate_W a b+ -- apply doubly-controlled not-gates+ zipWithM_ (dc_not h) a b+ comment_with_label "EXIT: basischange" (a,b,h) ("a","b","h")+ where+ dc_not h x y = qnot_at h `controlled` (x .==. 1 .&&. y .==. 0)+ +-- | Compute the required number of iterations as a function of ε and+-- /dt/.+-- +-- Inputs: /n/ is the tree depth, ε is the desired precision, /dt/ is+-- the simulation time step. Intermediate values: /t/ is the+-- simulation time. Output: /s/, the upper bound on the number of+-- simulation time steps.+-- +-- Note: \[Childs et al\] specifies that /t/ should be chosen+-- uniformly at random within the interval 0 < /t/ ≤ /n/[sup 4]\/2ε.+-- Here, for simplicity, we just use /t/ = ⌊/n/[sup 4]\/2ε⌋. Also note+-- that this function is for information only, as it is not actually+-- used. Users should specify /s/ directly.+compute_steps :: Int -> Double -> Double -> Int+compute_steps n epsilon dt =+ floor (t / dt)+ where+ t = fromIntegral (n * n * n * n) / (2.0 * epsilon)++-- ======================================================================+-- * Oracle implementations++-- ** Blackbox oracle++-- | A blackbox oracle for testing. This just produces a labelled box+-- in place of the actual oracle circuit. The argument is the tree+-- height.+oracle_blackbox :: Int -> Oracle+oracle_blackbox n = + let m = n+2 in+ Oracle {+ n = n,+ m = m,+ k = 4,+ entrance = boollist_of_int_bh (n+2) 1,+ oraclefun = \c (a, b, r) ->+ do+ named_gate_at ("O(" ++ show c ++ ")") (a ++ b ++ [r])+ return ()+ }++-- ----------------------------------------------------------------------+-- ** A simple \"exponential\" oracle.++-- | This oracle, which works only for the fixed tree height 3, works+-- by explicitly listing all the edges. It serves only to illustrate+-- how the edge information is encoded. Listing all edges explicitly+-- obviously would not scale well to larger graphs.+oracle_simple :: Oracle+oracle_simple =+ let n = 3+ m = 5+ k = 4++ invalid = 0 -- also works correctly for invalid = 31+ invalid_vec = boollist_of_int_bh m invalid++ green = 0+ blue = 1+ red = 2+ black = 3++ edges :: Int -> [(Int, Int)]+ edges 0 = [(1,3), (2,5), (4,8), (6,12), (7,15), (9,17), (10,18),+ (13,21), (19,25), (22,27), (24,28), (26,29)]+ edges 1 = [(2,4), (3,6), (5,10), (7,14), (8,16), (11,19), (12,20),+ (17,24), (21,26), (23,27), (25,28), (29,30)]+ edges 2 = [(1,2), (3,7), (4,9), (5,11), (6,13), (14,22), (15,23),+ (16,24), (18,25), (20,26), (27,29), (28,30)]+ edges 3 = [(8,17), (9,18), (10,19), (11,20), (12,21), (13,22),+ (14,23), (15,16)]+ edges n = error ("oracle_simple: illegal color: " ++ show n)++ -- apply an (a,n1)-controlled not operation to (v,n2)+ multi_controlled_multi_not :: Int -> (Qulist, Qulist) -> (Int, Int) -> Circ ()+ multi_controlled_multi_not m (a,v) (n1, n2) = do+ let vec1 = boollist_of_int_bh m n1+ let vec2 = boollist_of_int_bh m n2+ bool_controlled_not v vec2 `controlled` a .==. vec1+ return ()++ -- the O_c circuit+ oracle_O :: Int -> (Qulist, Qulist) -> Circ ()+ oracle_O c (a,v) = do+ let e = edges c+ foreach e $ \(n1, n2) -> do+ multi_controlled_multi_not m (a,v) (n1, invalid `xor` n2)+ multi_controlled_multi_not m (a,v) (n2, invalid `xor` n1)++ -- the B_c circuit+ oracle_B :: (Qulist, Qulist) -> Circ ()+ oracle_B (v,b) =+ for 0 (m-1) 1 $ \i -> do+ qnot_at (b !! i) `controlled` (v !! i) .==. 1++ -- the R_c circuit+ oracle_R :: (Qulist, Qubit) -> Circ ()+ oracle_R (v,r) = do+ qnot_at r `controlled` v .==. invalid_vec++ -- the oracle circuit+ oraclefun :: Int -> (Qulist, Qulist, Qubit) -> Circ ()+ oraclefun c (a,b,r) = do+ comment_with_label "ENTER: oracle_simple" (a,b,r) ("a","b","r")+ with_ancilla_init invalid_vec $ \v -> do+ oracle_O c (a,v)+ oracle_B (v,b)+ oracle_R (v,r)+ oracle_O c (a,v)+ comment_with_label "EXIT: oracle_simple" (a,b,r) ("a","b","r")++ in++ -- return the oracle object+ Oracle { n = n,+ m = m,+ k = k,+ entrance = boollist_of_int_bh m 1,+ oraclefun = oraclefun+ }++-- ======================================================================+-- ** Alternate implementations of the \"orthodox\" oracle++-- ----------------------------------------------------------------------+-- *** Classical implementation++-- $ In this section, we first implement the oracle function +-- /v[sub c](a)/ as a classical boolean function. This implementation+-- is just for reference, and attempts to be neither efficient nor+-- quantum. It can, however, be used as a specification to test the +-- actual quantum oracles against. +-- +-- Both the classical circuit implementation (below) and the Template+-- Haskell implementation (in the module "BWT.Template") were derived+-- from this.+-- +-- We start with several auxiliary functions.++-- | The type of nodes: a pair of a tree bit and a node address.+type Node = (Bool, [Bool])++-- | Convert integers to nodes, mainly for testing.+node_of_int :: Int -> Int -> Node+node_of_int m a = node_of_boollist (boollist_of_int_bh m a)++-- | Convert nodes to integers, mainly for testing.+int_of_node :: Node -> Int+int_of_node n = int_of_boollist_unsigned_bh (boollist_of_node n)++-- | Convert a bit vector to a node.+node_of_boollist :: [Bool] -> Node+node_of_boollist (t:a) = (t,a)+node_of_boollist [] = error "node_of_boollist: empty boollist"++-- | Convert a node to a bit vector.+boollist_of_node :: Node -> [Bool]+boollist_of_node (t,a) = t:a++-- | Input a node /a/ and return the parent of /a/. We assume that /a/+-- is not a root or invalid.+parent :: Node -> Node+parent (t, aa) = (t, False : init aa)++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True',+-- respectively). Assumes that /a/ is not a leaf.+childintree :: Node -> Bool -> Node+childintree (t, h:aa) childbit = (t, aa ++ [childbit])+childintree _ _ = error "childintree: invalid node"++-- | @'bit_adder' 'False'@ is a one-bit adder, and @'bit_adder' 'True'@ is+-- a one-bit subtracter (i.e., add the 2's complement of /y/).+bit_adder :: Bool -> (Bool, Bool, Bool) -> (Bool, Bool)+bit_adder sign (carry, x, y) = (carry', z)+ where+ y' = y `bool_xor` sign+ z = carry `bool_xor` x `bool_xor` y'+ carry' = majority carry x y'+ majority a b c = if a==b then a else c++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit; /a/+-- is the highest bit and /aa/ is the remaining /n/ bits) and a sign+-- /s/ (where 'True' = negative, 'False' = positive). Return+-- /a/:(/aa/ + /s/ * /f/). The first input is the /n/-bit welding+-- vector /f/ (a parameter to the oracle). Note that /f/ is a+-- parameter and /s/, /aa/ are inputs.+doweld1 :: Boollist -> Bool -> [Bool] -> [Bool]+doweld1 f s (a:aa) = a : aa' where+ aa' = snd $ fold_right_zip (bit_adder s) (s, aa, f)+doweld1 f s [] = error "doweld1: invalid node"++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit), and+-- return /a/:(/aa/ ⊕ /g/). The first input is the /n/-bit welding+-- vector /g/ (a parameter to the oracle).+doweld0 :: Boollist -> [Bool] -> [Bool]+doweld0 g (a:aa) = a : aa' where+ aa' = g `boollist_xor` aa+doweld0 g [] = error "doweld0: invalid node"++-- | Input a leaf node /a/ and return the left or right weld of /a/ in+-- the other tree (depending on whether the /weldbit/ is 'False' or+-- 'True'). Assumes that /a/ is a leaf.+weld :: Boollist -> Boollist -> Node -> Bool -> Node+weld f g (t, aa) weldbit = (not t, bb)+ where+ bb = if weldbit+ then doweld1 g t aa+ else doweld0 f aa++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True'. This+-- works for leaf and non-leaf nodes.+child :: Boollist -> Boollist -> Node -> Bool -> Node+child f g (t, aa) childbit =+ case aa of+ True : _ -> -- This is a leaf+ weld f g (t, aa) childbit+ False : _ -> -- This is not a leaf+ childintree (t, aa) childbit+ _ -> error "child: invalid node"++-- | Input a node address (without the tree bit) and return the parity+-- of the node level expressed as a boolean either 'False' or+-- 'True'. Leaves have parity 'False', and other levels have+-- alternating parities. In other words: count the number of leading+-- zeros modulo 2.+level_parity :: [Bool] -> Bool+level_parity [] = False+level_parity (h:t) = if h then False else not (level_parity t)++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node address is invalid. In other words, return 'True' iff the+-- list consists of all 0's.+is_zero :: [Bool] -> Bool+is_zero [] = True+is_zero (h:t) = if h then False else is_zero t++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node is a root or invalid. In other words, check whether all+-- digits but the last are 0's.+is_root :: [Bool] -> Bool+is_root [] = True+is_root (h:[]) = True+is_root (h:t) = if h then False else is_root t++-- | @'v_function' f g c a@: returns /v/[sub /c/](/a/), the label of the+-- node connected to /a/ by an edge of color /c/, or 'Nothing' if+-- there is no such node. The parameters /f/ and /g/ encode the+-- welding functions, and are lists of length /n/. /c/ is a color in+-- the range 0..3, and /a/ is an (/n/+2)-bit node label.+v_function :: Boollist -> Boollist -> Int -> Node -> Maybe Node+v_function f g c a =+ let (t,aa) = a+ bc_hi = level_parity aa+ z = is_zero aa+ e = is_root aa+ a1 = if last aa then True else False+ [c_hi, c_lo] = boollist_of_int_bh 2 c+ [cbc_hi, cbc_lo] = [c_hi `bool_xor` bc_hi, c_lo]+ in+ if not e && [cbc_hi, cbc_lo] == [True, a1] then Just(parent a) else+ if not z && cbc_hi == False then Just(child f g a cbc_lo) else+ Nothing++-- ----------------------------------------------------------------------+-- *** Auxiliary functions++-- | The type of nodes: a pair of a tree bit and a node address.+type CNode = (Bit, Bitlist)++-- | Like 'CNode', but uses qubits instead of classical bits.+type QNode = (Qubit, [Qubit])++-- | Convert a 'Qulist' to a 'QNode'.+qnode_of_qulist :: Qulist -> QNode+qnode_of_qulist (t:a) = (t,a)+qnode_of_qulist [] = error "qnode_of_qulist: empty list"++-- | Convert a 'Bitlist' to a 'CNode'.+cnode_of_bitlist :: Bitlist -> CNode+cnode_of_bitlist (t:a) = (t,a)+cnode_of_bitlist [] = error "cnode_of_bitlist: empty list"++-- | Exclusive or operation on bit vectors.+cboollist_xor :: Bitlist -> Bitlist -> Circ Bitlist+cboollist_xor = zipWithM (\x y -> cgate_xor [x,y])++-- ----------------------------------------------------------------------+-- *** Classical circuit implementation++-- $ We now implement the oracle function v[sub c](a) as a classical+-- circuit, with /c/ as a parameter. We don't try to be clever or+-- efficient yet. The implementation follows the \"classical+-- implementation\" above, but must be reformulated due to the need to+-- work within the 'Circ' monad.++-- | Input a node /a/ and return the parent of /a/. We assume that /a/+-- is not a root or invalid.+cparent :: CNode -> Circ CNode+cparent (t, aa_in) = do+ comment_with_label "ENTER: cparent" (t, aa_in) ("t", "aa_in")+ false <- cinit False+ let aa_out = false : init aa_in+ comment_with_label "EXIT: cparent" (t, aa_out) ("t", "aa_out")+ return (t, aa_out)++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True',+-- respectively). Assumes that /a/ is not a leaf.+cchildintree :: CNode -> Bit -> Circ CNode+cchildintree (t, node_in@(h:aa)) childbit = do+ comment_with_label "ENTER: cchildintree" (t, node_in) ("t", "node_in")+ let node_out = aa ++ [childbit]+ comment_with_label "EXIT: cchildintree" (t, node_out) ("t", "node_out")+ return (t, node_out)+cchildintree _ _ = error "cchildintree: invalid node"++-- | @'bit_adder' 'False'@ is a one-bit adder, and @'bit_adder' 'True'@ is+-- a one-bit subtracter (i.e., add the 2's complement of /y/).+cbit_adder :: Bit -> (Bit, Bit, Bit) -> Circ (Bit, Bit)+cbit_adder sign (carry_in, x, y) = do+ comment_with_label "ENTER: cbit_adder" (sign, carry_in, x, y) ("sign", "carry_in", "x", "y")+ y' <- cgate_xor [y, sign]+ z <- cgate_xor [carry_in, x, y']+ carry_out <- cmajority carry_in x y'+ comment_with_label "EXIT: cbit_adder" (carry_out, z) ("carry_out", "z")+ return (carry_out, z)+ where+ cmajority a b c = do+ cond <- cgate_eq a b+ cgate_if cond a c++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit; /a/+-- is the highest bit and /aa/ is the remaining /n/ bits) and a sign+-- /s/ (where 'True' = negative, 'False' = positive). Return+-- /a/:(/aa/ + /s/ * /f/). The first input is the /n/-bit welding+-- vector /f/ (a parameter to the oracle). Note that /f/ is a+-- parameter and /s/, /aa/ are inputs.+cdoweld1 :: Boollist -> Bit -> Bitlist -> Circ Bitlist+cdoweld1 f s node_in@(a:aa) = do+ comment_with_label "ENTER: cdoweld1" (s, node_in) ("s", "node_in")+ f' <- cinit f+ (_,aa') <- fold_right_zipM (cbit_adder s) (s, aa, f')+ let node_out = a : aa'+ comment_with_label "EXIT: cdoweld1" node_out "node_out"+ return node_out+cdoweld1 f s [] = error "cdoweld1: invalid node"++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit), and+-- return /a/:(/aa/ ⊕ /g/). The first input is the /n/-bit welding+-- vector /g/ (a parameter to the oracle).+cdoweld0 :: Boollist -> Bitlist -> Circ Bitlist+cdoweld0 g node_in@(a:aa) = do+ comment_with_label "ENTER: cdoweld0" node_in "node_in"+ g' <- cinit g+ aa' <- g' `cboollist_xor` aa+ let node_out = a:aa'+ comment_with_label "EXIT: cdoweld0" node_out "node_out"+ return node_out+cdoweld0 g [] = error "cdoweld0: invalid node"++-- | Input a leaf node /a/ and return the left or right weld of /a/ in+-- the other tree (depending on whether the /weldbit/ is 'False' or+-- 'True'). Assumes that /a/ is a leaf.+cweld :: Boollist -> Boollist -> CNode -> Bit -> Circ CNode+cweld f g node_in@(t, aa) weldbit = do+ comment_with_label "ENTER: cweld" (node_in, weldbit) ("node_in", "weldbit")+ bb <- circ_if weldbit (+ cdoweld1 g t aa+ )(+ cdoweld0 f aa+ )+ t' <- cgate_not t+ let node_out = (t', bb)+ comment_with_label "EXIT: cweld" node_out "node_out"+ return node_out++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True'. This+-- works for leaf and non-leaf nodes.+cchild :: Boollist -> Boollist -> CNode -> Bit -> Circ CNode+cchild f g node_in@(t, a:aa) childbit = do+ comment_with_label "ENTER: cchild" (node_in, childbit) ("node_in", "childbit")+ node_out <- circ_if a (+ -- This is a leaf+ cweld f g (t, a:aa) childbit+ )( + -- This is not a leaf+ cchildintree (t, a:aa) childbit+ )+ comment_with_label "EXIT: cchild" node_out "node_out"+ return node_out++cchild f g (t, _) childbit = + error "cchild: invalid node"++-- | Input a node address (without the tree bit) and return the parity+-- of the node level expressed as a boolean either 'False' or+-- 'True'. Leaves have parity 'False', and other levels have+-- alternating parities. In other words: count the number of leading+-- zeros modulo 2.+clevel_parity :: Bitlist -> Circ Bit+clevel_parity node = do+ comment_with_label "ENTER: clevel_parity" node "node"+ parity <- clevel_parity_rec node+ comment_with_label "EXIT: clevel_parity" parity "parity"+ return parity++ where+ clevel_parity_rec :: Bitlist -> Circ Bit+ clevel_parity_rec [] = cinit False+ clevel_parity_rec (h:t) = do+ r <- clevel_parity_rec t+ circ_if h (+ cinit False+ )(+ cgate_not r+ )++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node address is invalid. In other words, return 'True' iff the+-- list consists of all 0's.+cis_zero :: Bitlist -> Circ Bit+cis_zero node = do+ comment_with_label "ENTER: cis_zero" node "node"+ is_zero <- cis_zero_rec node+ comment_with_label "EXIT: cis_zero" is_zero "is_zero"+ return is_zero+ + where+ cis_zero_rec :: Bitlist -> Circ Bit+ cis_zero_rec [] = cinit True+ cis_zero_rec (h:t) = do+ circ_if h (+ cinit False+ )(+ cis_zero_rec t+ )++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node is a root or invalid. In other words, check whether all+-- digits but the last are 0's.+cis_root :: Bitlist -> Circ Bit+cis_root node = do+ comment_with_label "ENTER: cis_root" node "node"+ is_root <- cis_root_rec node+ comment_with_label "EXIT: cis_root" is_root "is_root"+ return is_root++ where+ cis_root_rec :: Bitlist -> Circ Bit+ cis_root_rec [] = cinit True+ cis_root_rec (h:[]) = cinit True+ cis_root_rec (h:t) = do+ circ_if h (+ cinit False+ )(+ cis_root_rec t+ )++-- | @'cv_function' f g c a@: returns /v/[sub /c/](/a/), the label of the+-- node connected to /a/ by an edge of color /c/, or 'Nothing' if+-- there is no such node. The parameters /f/ and /g/ encode the+-- welding functions, and are lists of length /n/. /c/ is a color in+-- the range 0..3, and /a/ is an (/n/+2)-bit node label.+-- +-- We currently implement @'Maybe' 'CNode'@ as an indexed union, and+-- specifically as @('CNode','Bit')@. When /Bit/='True', the value of+-- 'CNode' is undefined (doesn't matter); in particular, this value+-- may contain garbage.+cv_function :: Boollist -> Boollist -> Int -> CNode -> Circ (CNode,Bit)+cv_function f g color a = do+ comment_with_label (printf "ENTER: cv_function (color=%d)" color) a "a"+ let (t,aa) = a+ bc_hi <- clevel_parity aa+ z <- cis_zero aa+ e <- cis_root aa+ let a1 = last aa+ let [c_hi', c_lo'] = boollist_of_int_bh 2 color+ c_hi <- cinit c_hi'+ c_lo <- cinit c_lo'+ cbc_hi <- cgate_xor [c_hi, bc_hi]+ let cbc_lo = c_lo+ not_e <- cgate_not e+ cbc_lo_eq_a1 <- cgate_eq cbc_lo a1+ cond1 <- cgate_and [not_e, cbc_hi, cbc_lo_eq_a1]+ (b, invalid) <- circ_if cond1 (+ do + cparent_a <- cparent a+ false <- cinit False+ return (cparent_a, false)+ )(+ do+ cchild_a_cbc_lo <- cchild f g a cbc_lo+ not_z <- cgate_not z+ cbc_hi_eq_false <- cgate_not cbc_hi+ valid <- cgate_and [not_z, cbc_hi_eq_false]+ not_valid <- cgate_not valid+ -- a slight optimization here: we return garbage in the+ -- first register if not_valid == True+ return (cchild_a_cbc_lo, not_valid)+ )+ comment_with_label (printf "EXIT: cv_function (color=%d)" color) (b, invalid) ("b", "invalid")+ return (b, invalid)++-- ======================================================================+-- *** Oracle abstraction++-- | The classical oracle implementation, packaged into the 'Oracle'+-- abstraction. This oracle has two parameters, namely the welding+-- vectors /f/ and /g/. Note: this oracle has not been optimized+-- whatsoever.+oracle_classical :: Boollist -> Boollist -> Oracle+oracle_classical f g =+ Oracle { n = n,+ m = m,+ k = k,+ entrance = entrance,+ oraclefun = oraclefun+ } where+ n = length f+ m = n+2+ k = 4+ entrance = boollist_of_int_bh m 1+ + oraclefun :: Int -> (Qulist, Qulist, Qubit) -> Circ ()+ oraclefun color (a,b,r) = do+ let an = qnode_of_qulist a+ let bn = qnode_of_qulist b+ (classical_to_quantum . classical_to_reversible) (cv_function f g color) (an, (bn, r))+ return ()+ +-- ======================================================================+-- * Testing functions++-- | Output the list of colored edges as computed by the classical+-- 'v_function', for some arbitrary choice of /f/ and /g/ and /n/=3.+main_edges1 :: IO()+main_edges1 = mapM_ output (sample_all0 (127,3))+ where+ f = take 5 (True : False : f) + g = take 5 (False : True : g)+ + output :: (Int,Int) -> IO()+ output (a,c) =+ case v_function f g c (node_of_int 7 a) of+ Nothing -> printf "%d ---%d---> None\n" a c+ Just b -> printf "%d ---%d---> %d\n" a c (int_of_node b)++-- | For debugging: 'circfun' is similar to 'v_function', except it+-- works by calling 'cv_function' to assemble the circuit, then+-- simulates it. This is for testing whether the assembled circuit is+-- correct. Returns @('Bool', 'Node')@ instead of @'Maybe' 'Node'@, so+-- that we can see any garbage that is output in case of an invalid+-- node.+circfun :: Boollist -> Boollist -> Int -> Node -> (Node, Bool)+circfun f g color nd = + run_classical_generic (cv_function f g color) nd++-- | Output the list of colored edges as computed by simulating the+-- circuit 'cv_function', for some arbitrary choice of /f/ and /g/ and+-- /n/=3. This is like 'main_edges1', except it actually assembles and+-- simulates the classical circuit.+main_edges2 :: IO()+main_edges2 = mapM_ output (sample_all0 (127,3))+ where+ f = take 5 (True : False : f) + g = take 5 (False : True : g)+ output :: (Int,Int) -> IO()+ output (a,c) =+ case circfun f g c (node_of_int 7 a) of+ (node, False) -> printf "%d ---%d---> %d\n" a c (int_of_node node)+ (garbage, True) -> printf "%d ---%d---> None (%d)\n" a c (int_of_node garbage)+ +-- | Graphically output the classical oracle circuit for color /c/,+-- using /n/ from the oracle data structure, and for some arbitrary+-- /f/ and /g/.+main_oraclec :: Format -> BWT.Oracle -> Int -> IO()+main_oraclec format oracle color =+ print_generic format circuit cnode_shape+ where+ m' = BWT.m oracle+ n' = BWT.n oracle+ f = take n' (True : False : f)+ g = take n' (False : True : g)+ cnode_shape = cnode_of_bitlist (replicate m' bit)+ circuit n = cv_function f g color n++-- | Like 'main_oraclec', except it rewrites the classical circuit in+-- terms of Toffoli gates.+main_oracle2 :: Format -> BWT.Oracle -> Int -> IO()+main_oracle2 format oracle color =+ print_generic format circuit cnode_shape+ where+ m' = BWT.m oracle+ n' = BWT.n oracle+ f = take n' (True : False : f)+ g = take n' (False : True : g)+ cnode_shape = cnode_of_bitlist (replicate m' bit)+ circuit n = classical_to_cnot (cv_function f g color n)++-- | Like 'main_oraclec', except it makes the classical circuit+-- reversible first.+main_oracle3 :: Format -> BWT.Oracle -> Int -> IO()+main_oracle3 format oracle color =+ print_generic format circuit (cnode_shape, (cnode_shape, qubit))+ where+ m' = BWT.m oracle+ n' = BWT.n oracle+ f = take n' (True : False : f)+ g = take n' (False : True : g)+ cnode_shape = qnode_of_qulist (replicate m' qubit)+ circuit = (classical_to_quantum . classical_to_reversible) (cv_function f g color)++-- | Output the top-level circuit for the binary welded tree algorithm+-- with the classical oracle, using some arbitrary welding vectors /f/+-- and /g/, and /s/=1.+main_qrwbwt :: IO()+main_qrwbwt =+ print_simple EPS (qrwbwt (oracle_classical f g) dt 1)+ where + f = [False, False, True]+ g = [True, False, True]+ dt = pi/180
@@ -0,0 +1,600 @@+-- | This module provides an implementation of the main binary welded+-- tree algorithm and oracle, using a more-or-less imperative+-- programming style. We abstract the oracle into a data type, so that+-- different oracles can be plugged into the main algorithm.++module Quipper.Algorithms.BWT.BWT where++-- import other Quipper stuff+import Quipper+import Quipper.Algorithms.BWT.Definitions++import Quipper.Libraries.Qureg+import Quipper.Libraries.Decompose++import Quipper.Utils.Auxiliary++import Text.Printf++-- ======================================================================+-- * Oracle abstraction++-- | A data structure to hold an oracle. The binary welded tree+-- algorithm is parametric on an oracle. An oracle encodes a graph,+-- and provides the following information: the tree depth /n/ (in the+-- above example: 3), the label length /m/ (in bits; 5 in the above+-- example), the number of edge colors /k/, the entrance label+-- /ENTRANCE/, and for each color 0 ≤ /c/ < /k/, a reversible circuit+-- /ORACLE/[sub /c/](/a/,/b/,/r/). On basis vectors, this circuit+-- encodes the edge information in the following sense:+-- +-- > ORACLE[sub c](a, b, r) = (a, b ⊕ v[sub c](a), r ⊕ f[sub c](a)),+-- +-- where /f/[sub /c/](/a/) is 1 if the node /a/ is connected to an+-- edge of color /c/, and 0 otherwise; and /v/[sub /c/](a) is the+-- node label connected to node /a/ along an edge of color /c/ (if+-- any), and arbitrary otherwise. +-- +-- Not all available node labels need to be used (for example, 0 and+-- 16 are unused in the graph in the above illustration).++data Oracle = Oracle {+ n :: Int,+ m :: Int,+ k :: Int,+ entrance :: Boollist,+ oraclefun :: Int -> (Qureg, Qureg, Qubit) -> Circ ()+}++-- ======================================================================+-- * Top-level algorithm++-- | The main loop of the binary welded tree algorithm. +-- +-- @qrwbwt oracle s dt@: Do a quantum random walk on the binary welded+-- tree given by the oracle /oracle/, for /s/ times steps of length+-- /dt/. Returns a bit list corresponding to the computed exit node+-- label.++qrwbwt :: Oracle -> Int -> Timestep -> Circ [Bit]+qrwbwt oracle s dt = do+ comment (printf "ENTER: qrwbwt (s=%d, dt=%.3e)" s dt)+ -- initialize a to the entrance label+ a <- qinit_register (entrance oracle)+ with_ancilla_reg (m oracle) $ \b -> do+ with_ancilla $ \r -> do+ loopM_boxed_if (s > 1) "qrwbwt_loop" s (a,b,r) $ \(a,b,r) -> do+ for 0 (k oracle-1) 1 $ \c -> do+ (oraclefun oracle) c (a, b, r)+ timestep (a, b, r, dt, m oracle)+ (oraclefun oracle) c (a, b, r)+ endfor+ return (a,b,r)+ endfor+ exit <- qmeasure_register a+ comment_with_label "EXIT: qrwbwt" exit "exit"+ return exit++-- | @timestep (a, b, r, dt, m)@: Perform a single time step /dt/ of+-- the quantum walk. This is done by iterating through each of the+-- available edge colors, and performing a diffusion step for each+-- color. Here, /a/ is an /m/-qubit registers holding (a superposition+-- of) the current node label. /b/ is an /m/-qubit ancilla register,+-- and /r/ is an ancilla qubit. Both /b/ and /r/ are expected to be+-- initialized to |0〉 by the caller, and will be returned in state+-- |0〉.+timestep :: (Qureg, Qureg, Qubit, Timestep, Int) -> Circ ()+timestep (a, b, r, dt, m) = do+ comment_with_label "ENTER: timestep" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ for 0 (m-1) 1 $ \i -> do+ wGate (a.!(i), b.!(i))+ endfor+ for 0 (m-1) 1 $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ controlledExpGate (dt, r, h)+ for (m-1) 0 (-1) $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ for (m-1) 0 (-1) $ \i -> do+ wGateInverse (a.!(i), b.!(i))+ endfor+ comment_with_label "EXIT: timestep" (a,b,r) ("a","b","r")+ return ()++-- ======================================================================+-- * Oracle implementation++-- $ The functions in this section implement a particular oracle for a+-- binary welded tree. The oracle is parametric on:+-- +-- * the tree depth /n/;+-- +-- * two \"welding vectors\" /f/ and /g/, specifying how the leaves of+-- the two binary trees are connected to each other. Specifically, /f/+-- and /g/ encode the permutations of leaves given by a ↦ a ⊕ f and +-- a ↦ a + g, respectively, where \"⊕\" denotes bitwise exclusive or,+-- and \"+\" denotes binary addition.++-- ----------------------------------------------------------------------+-- ** Oracle subroutines++-- | The top-level oracle circuit. The arguments are of the form (/a/,+-- /b/, /r/, /color/, /f/, /g/, /n/), where /a/, /b/ are quantum+-- registers of length /n/+2, /color/ is a boolean register of length+-- 2, and /f/ and /g/ are boolean registers of length /n/.+oracle :: (Qureg, Qureg, Qubit, Boolreg, Boolreg, Boolreg, Int) -> Circ ()+oracle (a, b, r, color, f, g, n) = do+ let c = int_of_boolreg_unsigned_le color :: Int+ comment_with_label (printf "ENTER: oracle (color=%d)" c) (a,b,r) ("a","b","r")+ with_ancilla $ \root -> do+ with_ancilla $ \even -> do+ with_ancilla $ \isparent -> do+ with_ancilla $ \ischild -> do+ with_ancilla $ \direction -> do+ with_ancilla $ \ismatch -> do+ parseNodeRoot (a, root, even, n)+ parseNodeEven (a, even, n)+ testIsParent (a, root, even, isparent, color, n, 1, ismatch)+ testIsChild (even, ischild, direction, color, n)+ setParent (a, b, isparent, n)+ setChild (a, b, ischild, direction, f, g, n)+ with_controls (isparent .==. 0 .&&. ischild .==. 0) $ do {+ qnot_at r+ }+ testIsChild (even, ischild, direction, color, n)+ testIsParent (a, root, even, isparent, color, n, 0, ismatch)+ parseNodeEven (a, even, n)+ parseNodeRoot (a, root, even, n)+ comment_with_label (printf "EXIT: oracle (color=%d)" c) (a,b,r) ("a","b","r")+ return ()++-- | Input a node label /a/ of length at least /n/+1. Negate both+-- /root/ and /even/ if /a/ is a root node.+parseNodeRoot :: (Qureg, Qubit, Qubit, Int) -> Circ ()+parseNodeRoot (a, root, even, n) = do+ comment_with_label "ENTER: parseNodeRoot" (a, root, even) ("a", "root", "even")+ with_ancilla_reg (n+1) $ \scratch -> do+ for n 1 (-1) $ \index -> do + with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ endfor+ with_controls (scratch.!(0) .==. 0) $ do {+ qnot_at root;+ qnot_at even+ }+ for 1 n 1 $ \index -> do + with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1))+ }+ endfor+ comment_with_label "EXIT: parseNodeRoot" (a, root, even) ("a", "root", "even")+ return ()+ +-- | Input a node label /a/ of length at least /n/+1. Negate /even/+-- if the node /a/ occurs at an even height in the tree.+parseNodeEven :: (Qureg, Qubit, Int) -> Circ ()+parseNodeEven (a, even, n) = do+ comment_with_label "ENTER: parseNodeEven" (a, even) ("a", "even")+ with_ancilla_reg (n+1) $ \scratch -> do+ for n 1 (-1) $ \index -> do+ with_controls (scratch.!(n) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1));+ with_controls (Prelude.even index) $ do {+ qnot_at even+ }+ }+ with_controls (scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(n))+ }+ endfor+ for 1 n 1 $ \index -> do+ with_controls (scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(n))+ } + with_controls (scratch.!(n) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1))+ }+ endfor+ comment_with_label "EXIT: parseNodeEven" (a, even) ("a", "even")+ return ()++-- | Input a node label /a/ of length at least 1, and flags /root/+-- and /even/ describing whether /a/ is a root and at an even level,+-- respectively. Negate /isparent/ if /a/ has a parent of color+-- /color/ in the tree. +-- +-- The qubit /ismatch/ is an ancilla, and /really/ is either 0 or+-- 1. They are jointly used to control uncomputation, so that the+-- following sequence will compute and then uncompute 'testIsParent':+-- +-- > ismatch <- qinit 0+-- > testIsParent (a, root, even, isparent, color, n, 1, ismatch)+-- > testIsParent (a, root, even, isparent, color, n, 0, ismatch)+-- > qterm 0 ismatch+testIsParent :: (Qureg, Qubit, Qubit, Qubit, Boolreg, Int, Int, Qubit) -> Circ ()+testIsParent (a, root, even, isparent, color, n, really, ismatch) = do+ let c = int_of_boolreg_unsigned_le color :: Int+ comment_with_label (printf "ENTER: testIsParent (color=%d really=%d)" c really) (a, root, even, isparent, ismatch) ("a", "root", "even", "isparent", "ismatch")+ with_controls (really == 0) $ do {+ with_controls (root .==. 0 .&&. ismatch .==. 1) $ do {+ qnot_at isparent+ }+ }+ if color.!(1) == 1+ then+ if color.!(0) == 1 then+ with_controls (even .==. 1 .&&. a.!(0) .==. 1) $ do {+ qnot_at ismatch+ }+ else+ with_controls (even .==. 1 .&&. a.!(0) .==. 0) $ do {+ qnot_at ismatch+ }+ else+ if color.!(0) == 1 then+ with_controls (even .==. 0 .&&. a.!(0) .==. 1) $ do {+ qnot_at isparent+ }+ else+ with_controls (even .==. 0 .&&. a.!(0) .==. 0) $ do {+ qnot_at isparent+ }+ with_controls (root .==. 0 .&&. ismatch .==. 1) $ do {+ qnot_at isparent+ }+ comment_with_label (printf "EXIT: testIsParent (color=%d really=%d)" c really) (a, root, even, isparent, ismatch) ("a", "root", "even", "isparent", "ismatch")+ return ()++-- | Consider a node /a/, and negate /ischild/ if /a/ has a child+-- node of color /color/. Also set /direction/ to indicate whether+-- it is a \"left\" or \"right\" child. Here, /color/ is a boolean+-- register of length 2, representing a color. This function is+-- self-inverse.+testIsChild :: (Qubit, Qubit, Qubit, Boolreg, Int) -> Circ ()+testIsChild (even, ischild, direction, color, n) = do+ comment_with_label "ENTER: testIsChild" (even, ischild, direction) ("even", "ischild", "direction")+ if color.!(1) == 1+ then+ with_controls (even .==. 0) $ do {+ qnot_at ischild+ }+ else+ with_controls (even .==. 1) $ do {+ qnot_at ischild+ }+ with_controls (color.!(0) == 1) $ do {+ qnot_at direction+ }+ comment_with_label "EXIT: testIsChild" (even, ischild, direction) ("even", "ischild", "direction")+ return ()++-- | Input a node label /a/ of length at least /n/+2, and a flag+-- /isparent/ that has been initialized accordingly. Also input a+-- register /b/ of length at least /n/+2, initialized to |0〉. If+-- /isparent/ is set, set /b/ to the node label of the parent of+-- /a/. This is self-inverse.+setParent :: (Qureg, Qureg, Qubit, Int) -> Circ ()+setParent (a, b, isparent, n) = do+ comment_with_label "ENTER: setParent" (a, b, isparent) ("a", "b", "isparent")+ for 0 (n-1) 1 $ \index -> do+ with_controls (isparent .==. 1 .&&. a.!(index+1) .==. 1) $ do {+ qnot_at (b.!(index))+ }+ endfor+ with_controls (isparent .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at (b.!(n+1))+ }+ comment_with_label "EXIT: setParent" (a, b, isparent) ("a", "b", "isparent")+ return ()++-- | Similar to 'setParent', but set /b/ to the node label of the+-- indicated child of /a/. Here /a/ and /b/ are quantum registers of+-- length at least /n/+2, and /f/ and /g/ are boolean registers of+-- length /n/.+setChild :: (Qureg, Qureg, Qubit, Qubit, Boolreg, Boolreg, Int) -> Circ ()+setChild (a, b, ischild, direction, f, g, n) = do+ comment_with_label "ENTER: setChild" (a, b, ischild, direction) ("a", "b", "ischild", "direction")+ with_ancilla $ \childctrl -> do+ with_controls (ischild .==. 1 .&&. a.!(n) .==. 1) $ do {+ qnot_at childctrl+ }+ setWeld (a, b, childctrl, direction, f, g, n)+ with_controls (ischild .==. 1) $ do {+ qnot_at childctrl+ }+ setChildInTree (a, b, childctrl, direction, n)+ with_controls (ischild .==. 1 .&&. a.!(n) .==. 0) $ do {+ qnot_at childctrl+ }+ comment_with_label "EXIT: setChild" (a, b, ischild, direction) ("a", "b", "ischild", "direction")+ return ()+ +-- | A special case of 'setChild', where the child is inside the same+-- binary tree (i.e., not via the welding). +setChildInTree :: (Qureg, Qureg, Qubit, Qubit, Int) -> Circ ()+setChildInTree (a, b, childctrl, direction, n) = do+ comment_with_label "ENTER: setChildInTree" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ with_controls (childctrl .==. 1 .&&. direction .==. 1) $ do {+ qnot_at (b.!(0))+ }+ for 1 n 1 $ \index -> do+ with_controls (childctrl .==. 1 .&&. a.!(index-1) .==. 1) $ do {+ qnot_at (b.!(index))+ }+ endfor+ with_controls (childctrl .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at (b.!(n+1))+ }+ comment_with_label "EXIT: setChildInTree" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ return ()++-- | A special case of 'setChild', where the child is in the opposite+-- binary tree, i.e., we follow one of the welding edges.+setWeld :: (Qureg, Qureg, Qubit, Qubit, Boolreg, Boolreg, Int) -> Circ ()+setWeld (a, b, childctrl, direction, f, g, n) = do+ comment_with_label "ENTER: setWeld" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ with_ancilla $ \weldctrl -> do+ with_controls (childctrl .==. 1 .&&. direction .==. 0) $ do {+ qnot_at weldctrl+ }+ doWeld0 (a, b, weldctrl, f, n)+ with_controls (childctrl .==. 1) $ do {+ qnot_at weldctrl+ }+ doWeld1 (a, b, weldctrl, g, n)+ with_controls (childctrl .==. 1 .&&. direction .==. 1) $ do {+ qnot_at weldctrl+ }+ with_controls (childctrl .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at (b.!(n+1))+ }+ with_controls (childctrl .==. 1) $ do {+ qnot_at (b.!(n));+ qnot_at (b.!(n+1))+ }+ comment_with_label "EXIT: setWeld" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ return ()++-- | Input a node label /a/, and a register /b/ initialized to+-- |0〉. If /weldctrl/ is set, set /b/ to the node connected to /a/+-- by the welding function /f/. This is self-inverse. Here, /a/ and+-- /b/ are quantum registers of length at least /n/+2, and /f/ is a+-- boolean register of length /n/.+doWeld1 :: (Qureg, Qureg, Qubit, Boolreg, Int) -> Circ ()+doWeld1 (a, b, weldctrl, g, n) = do+ comment_with_label "ENTER: doWeld1" (a, b, weldctrl) ("a", "b", "weldctrl")+ with_ancilla $ \addsub -> do+ with_controls (weldctrl .==. 1 .&&. a.!(n+1) .==. 0) $ do {+ qnot_at addsub+ }+ cAddNum (addsub, b, a, g, n)+ with_controls (weldctrl .==. 1) $ do {+ qnot_at addsub+ }+ cSubNum (addsub, b, a, g, n)+ with_controls (weldctrl .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at addsub+ }+ comment_with_label "EXIT: doWeld1" (a, b, weldctrl) ("a", "b", "weldctrl")+ return ()++-- | Input a node label /a/, and a register /b/ initialized to+-- |0〉. If /weldctrl/ is set, set /b/ to the node connected to /a/+-- by the welding function /g/. This is self-inverse. Here, /a/ and+-- /b/ are quantum registers of length at least /n/+2, and /g/ is a+-- boolean register of length /n/.+doWeld0 :: (Qureg, Qureg, Qubit, Boolreg, Int) -> Circ ()+doWeld0 (a, b, weldctrl, f, n) = do+ comment_with_label "ENTER: doWeld0" (a, b, weldctrl) ("a", "b", "weldctrl")+ for 0 (n-1) 1 $ \index -> do+ with_controls (weldctrl .==. 1) $ do {+ qnot_at (b.!(index)) `controlled` a.!(index) ./=. f.!(index)+ }+ endfor+ comment_with_label "EXIT: doWeld0" (a, b, weldctrl) ("a", "b", "weldctrl")+ return ()++-- | This function implements integer addition. Input a quantum+-- register /input/ and a boolean register /num/, representing+-- integers, and a quantum register /out/ initialized to |0〉. If+-- /control/ is set, set /out/ to /input/ + /num/, otherwise do+-- nothing. Here /input/ and /out/ are quantum registers of length at+-- least /n/, /num/ is a boolean register of length /n/.+cAddNum :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cAddNum (control, out, input, num, n) = do+ comment_with_label "ENTER: cAddNum" (control, out, input) ("control", "out", "input")+ -- we represent mask as 1 << maskbit+ with_ancilla_reg n $ \scratch -> do+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(0) .==. 1) $ do {+ qnot_at (out.!(0))+ }+ with_controls (num.!(maskbit) /= 0) $ do {+ with_controls (control .==. 1) $ do {+ qnot_at (out.!(0))+ };+ with_controls (input.!(0) .==. 1) $ do {+ qnot_at (scratch.!(0))+ }+ }+ for 1 (n-1) 1 $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(index) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. control .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (control .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ cAddNumClear (control, scratch, input, num, n)+ comment_with_label "EXIT: cAddNum" (control, out, input) ("control", "out", "input")+ return ()++-- | A helper function for clearing the scratch space used by 'cAddNum'.+cAddNumClear :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cAddNumClear (control, scratch, input, num, n) = do+ comment_with_label "ENTER: cAddNumClear" (control, scratch, input) ("control", "scratch", "input")+ -- we represent mask as 1 << maskbit+ for (n-1) 1 (-1) $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. input.!(0) .==. 1) $ do {+ qnot_at (scratch.!(0))+ }+ comment_with_label "EXIT: cAddNumClear" (control, scratch, input) ("control", "scratch", "input")+ return ()++-- | Like 'cAddNum', except subtract instead of adding. +cSubNum :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cSubNum (control, out, input, num, n) = do+ comment_with_label "ENTER: cSubNum" (control, out, input) ("control", "out", "input")+ -- we represent mask as 1 << maskbit+ with_ancilla_reg n $ \scratch -> do+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(0) .==. 1) $ do {+ qnot_at (out.!(0))+ }+ with_controls (num.!(maskbit) /= 0) $ do {+ with_controls (control .==. 1) $ do {+ qnot_at (out.!(0))+ };+ with_controls (input.!(0) .==. 0) $ do {+ qnot_at (scratch.!(0))+ }+ }+ for 1 (n-1) 1 $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(index) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. control .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (control .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 0) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ cSubNumClear (control, scratch, input, num, n)+ comment_with_label "EXIT: cSubNum" (control, out, input) ("control", "out", "input")+ return ()++-- | A helper function for clearing the scratch space used by 'cSubNum'.+cSubNumClear :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cSubNumClear (control, scratch, input, num, n) = do+ comment_with_label "ENTER: cSubNumClear" (control, scratch, input) ("control", "scratch", "input")+ -- we represent mask as 1 << maskbit+ for (n-1) 1 (-1) $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 0) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. input.!(0) .==. 0) $ do {+ qnot_at (scratch.!(0))+ }+ comment_with_label "EXIT: cSubNumClear" (control, scratch, input) ("control", "scratch", "input")+ return ()++-- ----------------------------------------------------------------------+-- ** The oracle data structure++-- | This function inputs two welding functions /f/ and /g/, and+-- returns the oracle defined by the preceding functions. +-- +-- We call this the \"orthodox\" oracle, because the implementation+-- follows its specification very closely. For example, it uses a very+-- \"imperative\" programming style. For alternative implementations+-- of this and other oracles, see the modules+-- "Quipper.Algorithms.BWT.Alternative" and "Quipper.Algorithms.BWT.Template".+oracle_orthodox :: Boollist -> Boollist -> Oracle+oracle_orthodox f g =+ Oracle { n = n,+ m = m,+ k = k,+ entrance = entrance,+ oraclefun = oraclefun+ } where+ n = length f+ m = n+2+ k = 4+ entrance = boollist_of_int_bh m 1+ f_reg = boolreg_of_boollist_te f+ g_reg = boolreg_of_boollist_te g+ + oraclefun :: Int -> (Qureg, Qureg, Qubit) -> Circ ()+ oraclefun c (a,b,r) = do+ let color = boolreg_of_int_le 2 c+ oracle (a, b, r, color, f_reg, g_reg, n)+ return ()++-- ======================================================================+-- * Main functions++-- These functions are so that the user can output something.++-- | Output the circuit for the quantum walk and a binary welded tree,+-- for the given 'Oracle' in the specified 'Format' and using the+-- specified 'GateBase'. Use /s/ time steps of length /dt/.+main_circuit :: Format -> GateBase -> Oracle -> Int -> Timestep -> IO()+main_circuit format base oracle s dt =+ print_generic format (decompose_generic base circuit)+ where+ circuit = qrwbwt oracle s dt++-- | Output the circuit for the given 'Oracle' and the given color+-- (specified as an 'Int'). Use the specified output 'Format' and+-- 'GateBase'.+main_oracle :: Format -> GateBase -> Oracle -> Int -> IO()+main_oracle format base oracle c =+ let m' = m oracle + ofun = oraclefun oracle+ circuit = (\(a,b,r) -> ofun c (qureg_of_qulist_te a, qureg_of_qulist_te b, r))+ in+ print_generic format (decompose_generic base circuit) (replicate m' qubit, replicate m' qubit, qubit)
@@ -0,0 +1,35 @@+-- | This module provides some convenient definitions for the Binary+-- Welded Tree algorithm implementation.++module Quipper.Algorithms.BWT.Definitions where++import Quipper++-- ======================================================================+-- * Some convenient gates++-- | Apply the binary /W/-gate to a pair of qubits. The W-gate+-- diagonalizes the SWAP operation.+wGate :: (Qubit, Qubit) -> Circ ()+wGate (a,b) = do+ gate_W a b+ return ()++-- | Apply the /inverse/ of the /W/-gate. Note: since the /W/-gate is+-- self-inverse, this is really the same as 'wGate'. However, we+-- define this as a separate function for clarity. +wGateInverse :: (Qubit, Qubit) -> Circ ()+wGateInverse = wGate++-- | Apply a doubly-controlled not gate to a triple of qubits (/a/,+-- /b/, /c/). Here the qubit /c/ is negated if /a/=1 and /b/=0.+toffoliGate :: (Qubit, Qubit, Qubit) -> Circ ()+toffoliGate (a, b, c) =+ qnot_at c `controlled` (a .==. 1 .&&. b .==. 0)++-- | @controlledExpGate(t, r, h):@+-- Apply the [exp −/iZt/] gate to the qubit /h/, provided that /r/=0. +controlledExpGate :: (Timestep, Qubit, Qubit) -> Circ ()+controlledExpGate (t, r, h) = do+ expZt t h `controlled` (r .==. 0)+ return ()
@@ -0,0 +1,10 @@+import Quipper++and_gate :: (Qubit, Qubit) -> Circ (Qubit)+and_gate (a, b) = do+ c <- qinit False+ qnot_at c `controlled` [a, b]+ return c++main =+ print_simple Preview and_gate
@@ -0,0 +1,20 @@+import Quipper++and_gate :: (Qubit, Qubit) -> Circ (Qubit)+and_gate (a, b) = do+ c <- qinit False+ qnot_at c `controlled` [a, b]+ return c++and_list :: [Qubit] -> Circ Qubit+and_list [] = do+ c <- qinit True+ return c+and_list [q] = do+ return q+and_list (q:t) = do+ d <- and_list t+ e <- and_gate (d, q)+ return e++main = print_generic Preview and_list (replicate 10 qubit)
@@ -0,0 +1,26 @@+import Quipper++and_gate :: (Qubit, Qubit) -> Circ (Qubit)+and_gate (a, b) = do+ c <- qinit False+ qnot_at c `controlled` [a, b]+ return c++and_list :: [Qubit] -> Circ Qubit+and_list [] = do+ c <- qinit True+ return c+and_list [q] = do+ return q+and_list (q:t) = do+ d <- and_list t+ e <- and_gate (d, q)+ return e++and_rev :: ([Qubit], Qubit) -> Circ ([Qubit], Qubit)+and_rev = classical_to_reversible and_list++main =+ print_generic Preview and_rev (replicate 10 qubit, qubit)++
@@ -0,0 +1,13 @@+import Quipper+import Quipper.Libraries.Arith++main :: IO ()+main = print_generic Preview labelled_add (qdint_shape 3) (qdint_shape 3)+++labelled_add :: QDInt -> QDInt -> Circ (QDInt, QDInt,QDInt)+labelled_add x y = do+ label (x,y) ("x","y")+ xy <- q_add x y+ label xy ("x","y","x+y")+ return xy
@@ -0,0 +1,112 @@+import Quipper+import Quipper.Libraries.Unboxing++main :: IO ()+main = do+ print_generic Preview boxed_unboxed (replicate 5 qubit) (replicate 5 qubit)+ --print_simple Preview boxed_unboxed2+ --print_simple Preview boxed_unboxed3+ --print_simple Preview boxed_unboxed4++sub_notboxed :: [Qubit] -> Circ [Qubit]+sub_notboxed [] = return []+sub_notboxed [a] = return [a]+sub_notboxed (a:(b:cs)) = do+ a' <- hadamard a `controlled` b+ bcs' <- sub_notboxed (b:cs)+ return (bcs' ++ [a'])++sub_boxed :: [Qubit] -> Circ [Qubit]+sub_boxed = box "sub" sub_notboxed++my_circuit :: ([Qubit] -> Circ [Qubit]) -> [Qubit] -> [Qubit] -> Circ ([Qubit],[Qubit])+my_circuit sub as bs = do+ comment_with_label "ENTER: my_circuit" (as,bs) ("a","b")+ as' <- sub (reverse as) `controlled` (head bs)+ label (as',bs) ("a","b")+ bs' <- sub bs + label (as',bs') ("a","b")+ as'' <- reverse_generic_endo sub (reverse as') `controlled` (head bs')+ comment_with_label "EXIT: my_circuit" (as'',bs') ("a","b")+ return (as'',bs')++boxed_unboxed :: [Qubit] -> [Qubit] -> Circ ([Qubit],[Qubit])+boxed_unboxed as bs = do+ label (as,bs) ("a","b")+ (as,bs) <- my_circuit sub_notboxed as bs+ label (as,bs) ("a","b")+ (as,bs) <- my_circuit sub_boxed as bs+ label (as,bs) ("a","b")+ (as,bs) <- unbox (my_circuit sub_boxed) as bs+ label (as,bs) ("a","b")+ return (as,bs)++my_subroutine2 :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+my_subroutine2 (a,b,c) = do+ qnot_at c `controlled` [a,b]+ return (a,b,c)++sub2 :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+sub2 = box "tof" my_subroutine2++my_subroutine2' :: (Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit)+my_subroutine2' (a,b,c,d) = do+ (b',c',d') <- sub2 (b,c,d) `controlled` a+ return (a,b',c',d')++sub2' :: (Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit)+sub2' = box "ss" my_subroutine2'++my_circuit2 :: (Qubit,Qubit,Qubit,Qubit) -> (Qubit,Qubit,Qubit,Qubit) -> Circ ((Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit))+my_circuit2 as bs = do+ (a1,a2,a3,a4) <- sub2' as+ (b1,b2,b3,b4) <- sub2' bs + return ((a1,a2,a3,a4),(b1,b2,b3,b4))++boxed_unboxed2 :: (Qubit,Qubit,Qubit,Qubit) -> (Qubit,Qubit,Qubit,Qubit) -> Circ ((Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit))+boxed_unboxed2 as bs = do+ (as',bs') <- my_circuit2 as bs+ (as'',bs'') <- (unbox my_circuit2) as' bs'+ (unbox (unbox my_circuit2)) as'' bs''++my_subroutine3 :: (Qubit,Qubit,Qubit) -> Circ Qubit+my_subroutine3 (a,b,c) = do+ qdiscard (c,a)+ return b++sub3 :: (Qubit,Qubit,Qubit) -> Circ Qubit+sub3 = box "term" my_subroutine3++my_circuit3 :: (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit)+my_circuit3 (a,b,c,d,e,f) = do+ b' <- sub3 (a,b,c)+ e' <- sub3 (d,e,f)+ qnot_at e' `controlled` b' + return (b',e')++boxed_unboxed3 :: ((Qubit,Qubit,Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit)) -> Circ (Qubit,Qubit)+boxed_unboxed3 ((a,b,c,d,e,f),(c',d',e',f')) = do+ (a',b') <- my_circuit3 (a,b,c,d,e,f)+ (unbox my_circuit3) (a',b',c',d',e',f')++my_subroutine4 :: Qubit -> Circ (Qubit,Qubit,Qubit)+my_subroutine4 a = do+ (b,c) <- qinit (False,False)+ return (a,b,c)++sub4 :: Qubit -> Circ (Qubit,Qubit,Qubit)+sub4 = box "init" my_subroutine4++my_circuit4 :: (Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit)+my_circuit4 (a,b) = do+ (a',c,d) <- sub4 a + (b',e,f) <- sub4 b+ return (a',b',c,d,e,f)++boxed_unboxed4 :: (Qubit,Qubit) -> Circ ((Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit,Qubit,Qubit))+boxed_unboxed4 (a,b) = do+ (a',b',c,d,e,f) <- my_circuit4 (a,b)+ (a'',b'',g,h,i,j) <- unbox my_circuit4 (a',b')+ return ((c,d,e,f),(a'',b'',g,h,i,j))++
@@ -0,0 +1,36 @@+import Quipper++-- Unboxed version of subroutine+my_sub :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+my_sub (a,b,c) = do+ hadamard_at a `controlled` b+ hadamard_at a `controlled` c+ hadamard_at b `controlled` c+ return (a,b,c)+ +-- Boxed version of subroutine+boxed_sub :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+boxed_sub = box "my_sub" my_sub++-- Unboxed version of circuit+my_circuit :: [Qubit] -> Circ [Qubit]+my_circuit [] = return []+my_circuit [a] = return [a]+my_circuit [a,b] = return [a,b]+my_circuit (a:b:c:rest) = do+ (a,b,c) <- my_sub (a,b,c)+ x <- my_circuit (b:c:rest)+ return (a:x)++-- Boxed version of circuit+my_circuit_boxed :: [Qubit] -> Circ [Qubit]+my_circuit_boxed [] = return []+my_circuit_boxed [a] = return [a]+my_circuit_boxed [a,b] = return [a,b]+my_circuit_boxed (a:b:c:rest) = do+ (a,b,c) <- boxed_sub (a,b,c)+ x <- my_circuit_boxed (b:c:rest)+ return (a:x)++main = do+ print_generic Preview my_circuit_boxed (replicate 6 qubit)
@@ -0,0 +1,12 @@+import Quipper++circuit :: (Bit, Qubit) -> Circ (Qubit, Qubit)+circuit (b,q) = do+ qnot_at q `controlled` b+ r <- prepare b+ gate_W_at q r+ return (q,r)+ +main = + print_simple Preview circuit+
@@ -0,0 +1,25 @@+import Quipper++example1 :: (Qubit,Qubit,[Qubit]) -> Circ (Qubit,Qubit,[Qubit])+example1 (q, a, b) = do+ comment_with_label "Start of example 1" (q,a,b) ("q","a","b")+ hadamard a+ qnot_at a `controlled` b+ hadamard q `controlled` a+ qnot_at a `controlled` b+ hadamard a+ comment "End of example 1"+ return (q, a, b)++example3 :: (Qubit,Qubit,[Qubit],Qubit,Qubit) -> Circ (Qubit,Qubit,[Qubit],Qubit,Qubit)+example3 (q, a, b, d, e) = do+ comment_with_label "Start of example 3" (q,a,b,d,e) ("q","a","b","d","e")+ example1 (q, a, b)+ with_controls (d .==. 0 .&&. e .==. 1) $ do+ example1 (q, a, b)+ example1 (q, a, b)+ example1 (q, a, b)+ comment "End of example 3"+ return (q, a, b, d, e)++main = print_generic Preview example3 (qubit, qubit, replicate 3 qubit, qubit, qubit)
@@ -0,0 +1,63 @@+-- | Consider the following problem, suggested by Dmitry Maslov: Input+-- a list of bits. Let /i/ be the weight of the list, i.e., the number+-- of \"1\" bits in the list. Output the /i/th element, where elements+-- are counted from 0 and we wrap around cyclically if /i/ equals the+-- length of the list.++import Quipper+import Quipper.Libraries.Arith+import Quipper.Libraries.Qram++import Prelude hiding (truncate)++-- | Figure out how many bits are needed to store a given integer. +hibit :: Int -> Int+hibit 0 = 0+hibit n = 1 + hibit (n `div` 2)++-- | @'truncate' n q@: Input a classical integer /n/ and a quantum+-- integer /q/. Output /0/ if /q/=/n/, and /q/ otherwise. For the+-- problem at hand, this is cheaper than full modular arithmetic. +truncate :: IntM -> QDInt -> Circ QDInt+truncate n q = do+ q' <- qc_copy q+ with_controls (q .==. n) $ do+ controlled_not q' q+ return q'++-- | Input a list of qubits and return its weight.+weight :: [Qubit] -> Circ QDInt+weight qs = q where+ len = length qs+ bits = hibit len+ zero = intm bits 0+ q = do+ q <- qinit zero+ q <- aux qs q+ q1 <- truncate (intm bits (toInteger len)) q+ return q1++ aux [] q = return q+ aux (h:t) q = do+ q <- q_increment q `controlled` h+ q <- aux t q+ return q++-- | Input a list of qubits, and output the /i/th qubit, where /i/ is+-- the weight of the list.+countshift :: [Qubit] -> Circ Qubit+countshift qs = do+ q <- weight qs+ a <- indexed_access qs q+ return a++-- | Reversible version of 'countshift'. +countshift_rev :: [Qubit] -> Circ ([Qubit], Qubit)+countshift_rev qs = do+ b <- with_computed (countshift qs) $ \a -> do+ qc_copy a+ return (qs, b)++-- | A main function to print the circuit.+main = + print_generic Preview countshift_rev (replicate 7 qubit)
@@ -0,0 +1,23 @@+import Quipper+import Quipper.Libraries.Decompose++toffoli :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+toffoli (q1,q2,q3) = do+ qnot_at q3 `controlled` (q1,q2)+ return (q1,q2,q3)++boxed :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+boxed = box "Toffoli" toffoli+++tof :: (Qubit,Qubit,Qubit,Qubit,Qubit) -> Circ ()+tof (q1,q2,q3,q4,q5) = do+ boxed (q3,q4,q5) `controlled` (q1,q2)+ return ()+ +main :: IO ()+main = do+ print_simple Preview tof+ print_simple Preview (decompose_generic Logical tof)+ print_simple Preview (decompose_generic Toffoli tof)+ print_simple Preview (decompose_generic Binary tof)
@@ -0,0 +1,23 @@+-- Test the dynamic lifting feature. ++import Quipper++-- | A circuit in which some future gates depend on a prior measurement.+circuit :: Qubit -> Qubit -> Circ Qubit+circuit a b = do+ qnot_at a `controlled` b+ m <- measure a+ bool <- dynamic_lift m+ if bool == 0 then+ do+ hadamard_at b+ return b+ else+ do+ c <- qinit False+ qnot_at c `controlled` b+ qdiscard b+ return c++main = do+ print_simple ASCII circuit
@@ -0,0 +1,28 @@+import Quipper+import Quipper.Libraries.Decompose++-- Outputs a partially undefined circuit. This illustrates the use of+-- laziness in the Quipper circuit generation code.++-- Please note that currently only the ASCII backend can make actual+-- use of laziness; the graphics-based backends must generate the+-- whole circuit before it can be printed.++-- We also apply a transformer, to illustrate the laziness of+-- transformers as well.++circuit_with_error :: Qubit -> Qubit -> Qubit -> Circ (Qubit, Qubit, Qubit)+circuit_with_error q r s = do+ qnot_at q `controlled` [r,s]+ hadamard_at r+ error "A runtime error occurred!"+ hadamard_at r+ return (q, r, s) + +circuit_with_error_transformed = decompose_generic Binary circuit_with_error++main =+ print_simple ASCII circuit_with_error++main2 = + print_simple ASCII circuit_with_error_transformed
@@ -0,0 +1,37 @@++import Quipper+import Prelude hiding (and)++example1 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+example1 (a,b,c) = do+ qnot_at a `controlled` [b, c]+ hadamard b `controlled` [a]+ qnot_at a `controlled` [b, c]+ hadamard c `controlled` [a]+ return (a,b,c)++example2 :: Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example2 h a b c = do+ qnot_at c `controlled` [a, b]+ hadamard h `controlled` [c]+ qnot_at c `controlled` [a, b]++example3 :: Qubit -> Qubit -> Qubit -> Circ ()+example3 h a b = do+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard h `controlled` [c]+ qnot_at c `controlled` [a, b]++example4 :: (Qubit, Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit, Qubit)+example4 (a,b,c,d) = do+ qnot_at a+ qnot_at b+ with_controls (c .&&. d) $ do+ qnot_at a+ qnot_at b+ qnot_at c+ return (a,b,c,d)++main =+ print_simple Preview example4
@@ -0,0 +1,10 @@+ import Quipper++ example1 (q, a, b, c) = do+ hadamard a+ qnot_at c `controlled` [a, b]+ hadamard q `controlled` [c]+ qnot_at c `controlled` [a, b]+ hadamard a++ main = print_simple Preview example1
@@ -0,0 +1,12 @@+ import Quipper++ example2 (q, a, b) = do+ hadamard a+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard_at q `controlled` [c]+ qnot_at c `controlled` [a, b]+ hadamard_at a+ return (q, a, b)++ main = print_simple Preview example2
@@ -0,0 +1,21 @@+import Quipper++example1 :: (Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit)+example1 (q, a, b, c) = do+ hadamard a+ qnot_at c `controlled` [a, b]+ hadamard q `controlled` [c]+ qnot_at c `controlled` [a, b]+ hadamard a+ return (q, a, b, c)++example3 :: (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit)+example3 (q, a, b, c, d, e) = do+ example1 (q, a, b, c)+ with_controls (d .==. 0 .&&. e .==. 1) $ do+ example1 (q, a, b, c)+ example1 (q, a, b, c)+ example1 (q, a, b, c)+ return (q, a, b, c, d, e)++main = print_simple Preview example3
@@ -0,0 +1,11 @@+import Quipper++example4 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+example4(q, a, b) = do+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard q `controlled` [c]+ qnot_at c `controlled` [a, b]+ return (q, a, b)++main = print_simple Preview example4
@@ -0,0 +1,33 @@+-- This file illustrates how global phase gates will be rendered in+-- graphical circuit diagrams.++import Quipper++mycirc :: (Qubit, Qubit, Qubit) -> Circ ()+mycirc (a,b,c) = do+ comment "Unanchored"+ global_phase 1.0+ + comment "Anchored at a"+ global_phase_anchored 1.0 a+ + comment "Anchored at b"+ global_phase_anchored 1.0 b+ + comment "Anchored at c"+ global_phase_anchored 1.0 c+ + comment "Anchored at (a,b)"+ global_phase_anchored 1.0 (a,b)+ +test :: (Qubit, Qubit, Qubit) -> Circ ()+test (a,b,c) = do + label (a,b,c) ("a", "b", "c")+ mycirc (a,b,c)+ mycirc (a,b,c) `controlled` a+ mycirc (a,b,c) `controlled` b+ mycirc (a,b,c) `controlled` c+ mycirc (a,b,c) `controlled` a .==. 1 .&&. b .==. 0 .&&. c .==. 0++main = + print_simple Preview test
@@ -0,0 +1,11 @@+import Quipper++circuit :: Qubit -> Qubit -> Qubit -> Circ (Qubit, Qubit, Qubit, Qubit)+circuit a b c = do+ qnot_at a `controlled` c .==. 1+ hadamard_at b `controlled` c .==. 0+ d <- qinit False+ qnot_at d `controlled` b .==. 1+ return (a,b,c,d)++main = print_simple Preview circuit
@@ -0,0 +1,26 @@+import Quipper+import Quipper.Libraries.Decompose++-- Outputs an infinite circuit. This illustrates the use of laziness+-- in the Quipper circuit generation code. ++-- Please note that currently only the ASCII backend can make actual+-- use of laziness; the graphics-based backends must generate the+-- whole circuit before it can be printed.++-- We also apply a transformer, to illustrate the laziness of+-- transformers as well.++infinite_circuit :: Qubit -> Qubit -> Qubit -> Circ (Qubit, Qubit, Qubit)+infinite_circuit q r s = do+ qnot_at q `controlled` [r,s]+ hadamard_at r+ infinite_circuit s q r+ +infinite_circuit_transformed = decompose_generic Binary infinite_circuit++main1 = + print_simple ASCII infinite_circuit++main = + print_simple ASCII infinite_circuit_transformed
@@ -0,0 +1,30 @@+-- | Demonstrates Quipper's decomposition of multiply-controlled+-- not-gates into the Clifford+/T/ gate set.++import Quipper+import Quipper.Libraries.Decompose++multi_cnot :: [Qubit] -> Qubit -> Circ ()+multi_cnot controls target = do+ qnot_at target `controlled` controls++multi_cnot_decomposed :: [Qubit] -> Qubit -> Circ ()+multi_cnot_decomposed = decompose_generic Exact multi_cnot++main_n :: Int -> IO ()+main_n n = do+ putStrLn ("Gate counts for " ++ show n ++ " controls:")+ putStrLn ""+ print_generic GateCount multi_cnot_decomposed (replicate n qubit) qubit+ putStrLn ""+ print_generic Preview multi_cnot_decomposed (replicate n qubit) qubit+ +main :: IO ()+main = do+ main_n 0+ main_n 1+ main_n 2+ main_n 3+ main_n 4+ main_n 5+ main_n 6
@@ -0,0 +1,22 @@+import Quipper+import Quipper.Libraries.Unboxing++rep :: Integer+rep = 3++myfunc :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+myfunc (a,b) = do+ hadamard_at a `controlled` b+ return (b,a)+ +circuit :: (Qubit, Qubit, Qubit, Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit, Qubit, Qubit, Qubit)+circuit (a,b,c,d,e,f) = do+ label (a,b,c,d,e,f) ("a","b","c","d","e","f")+ (a,b) <- loopM rep (a,b) myfunc+ (c,d) <- box_loopM "box1" rep (c,d) myfunc+ (e,f) <- unbox (\x -> box_loopM "box1" rep x myfunc) (e,f)+ label (a,b,c,d,e,f) ("a","b","c","d","e","f") + return (a,b,c,d,e,f)+ +main = + print_simple Preview circuit
@@ -0,0 +1,30 @@+import Quipper hiding (gate_V)++my_unary_gate :: Qubit -> Circ Qubit+my_unary_gate = named_gate "Q"++my_binary_gate :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+my_binary_gate = named_gate "R"++my_unary_gate_at :: Qubit -> Circ ()+my_unary_gate_at = named_gate_at "Q"++my_binary_gate_at :: (Qubit, Qubit) -> Circ ()+my_binary_gate_at = named_gate_at "R"++gate_V :: Qubit -> Circ Qubit+gate_V = named_gate "V"++circuit :: Qubit -> Qubit -> Circ (Qubit, Qubit)+circuit a b = do+ a <- gate_V a+ (c,d) <- my_binary_gate (a,b)+ c <- my_unary_gate a `controlled` d+ my_binary_gate_at (c, d)+ my_binary_gate_at (d, c)+ my_unary_gate_at d+ c <- gate_V c+ d <- gate_V d+ return (c,d)++main = print_simple Preview circuit
@@ -0,0 +1,74 @@+import Quipper++-- | 'example1': do a basis change, then perform some operation, then+-- uncompute the basis change. Drawback: if this is later controlled,+-- then the controls are applied to the basis change too, which is+-- unnecessary.++example1 :: Qubit -> Qubit -> Circ ()+example1 a b = do+ -- basis change+ gate_W_at a b+ qnot_at b `controlled` a+ + -- some operation+ hadamard_at b `controlled` a+ + -- undo basis change+ qnot_at b `controlled` a+ gate_W_at a b ++-- | 'example2': low-level solution. The 'without_controls' operator+-- can be used to inhibit the addition of further controls to blocks+-- of code. (However, this is not very safe. A better way to do this+-- is shown in 'example3').++example2 :: Qubit -> Qubit -> Circ ()+example2 a b = do+ -- basis change+ without_controls $ do+ gate_W_at a b+ qnot_at b `controlled` a+ -- some operation+ hadamard_at b `controlled` a+ -- undo basis change+ without_controls $ do+ qnot_at b `controlled` a+ gate_W_at a b++-- | 'example3': a better way to achieve the effect of 'example2' is+-- to use the operator 'with_basis_change'. This will take care of the+-- uncomputation automatically, and also ensure that controls will not+-- be added to the basis change.+example3 :: Qubit -> Qubit -> Circ () +example3 a b = do+ with_basis_change basischange $ do+ hadamard_at b `controlled` a++ where+ basischange = do+ gate_W_at a b+ qnot_at b `controlled` a++-- | 'example4': a similar effect is introduced by the operator+-- 'with_ancilla'. Normally, the gates that initialize and terminate+-- ancillas cannot be controlled. However, when using the+-- 'with_ancilla' operator, the resulting circuit can be controlled as+-- a whole, provided that the body is controllable.++example4 :: Qubit -> Qubit -> Circ ()+example4 a b = do+ with_ancilla $ \d -> do+ with_basis_change (qnot_at d `controlled` b .==. False) $ do+ hadamard_at a `controlled` d++my_circuit :: Qubit -> Qubit -> Qubit -> Circ ()+my_circuit ctrl a b = do+ example1 a b `controlled` ctrl+ example2 a b `controlled` ctrl+ example3 a b `controlled` ctrl+ example4 a b `controlled` ctrl++main =+ print_simple Preview my_circuit+
@@ -0,0 +1,53 @@+-- | A test for the 'simplify_classical' function. As an example, we use+-- a simple adder defined using the @build_circuit@ keyword. 'main1'+-- outputs the unoptimized circuit, and 'main2' outputs the optimized+-- version.++import Quipper+import Quipper.Libraries.ClassicalOptim+import Quipper.Utils.Auxiliary++-- | Return the majority of three booleans.+build_circuit+majority :: Bool -> Bool -> Bool -> Bool+majority a b c = if (a `bool_xor` b) then c else a++-- | Bit adder. The first input is 'False' for adding, and 'True' for+-- subtracting. The second input is a triple consisting of a carry,+-- and two bits to be added. The output consists of the new carry and+-- the sum.+build_circuit+bit_adder :: Bool -> (Bool,Bool,Bool) -> (Bool,Bool)+bit_adder sign (carry, x,y) =+ let y' = y `bool_xor` sign in+ let z = carry `bool_xor` x `bool_xor` y' in+ let carry' = majority carry x y' in+ (carry', z)++-- | Multi-bit adder. Add two /n/-bit integers, represented as+-- little-tailian bit lists.+build_circuit+adder :: [Bool] -> [Bool] -> [Bool]+adder f l = + reverse $ snd $ fold_right_zip (bit_adder False) (False, reverse l, reverse f)++-- | Wrapper around 'template_adder'.+myAdder :: ([Qubit],[Qubit]) -> Circ [Qubit]+myAdder (x,y) = do+ label (x,y) ("x","y")+ z <- unpack template_adder x y+ label z "z"+ return (z)++main1 :: IO()+main1 = do+ print_generic Preview myAdder (replicate 3 qubit, replicate 3 qubit)++main2 :: IO()+main2 = do+ print_generic Preview (simplify_classical myAdder) (replicate 3 qubit, replicate 3 qubit)++main :: IO()+main = main2++
@@ -0,0 +1,39 @@+import Quipper++import Quipper.Libraries.Qureg++-- | Algorithm 7. The arguments are of the form (/a/, /root/, /even/,+-- /n/). Precondition: /a/ is a quantum register of length at least+-- /n/+1.+parseNodeRoot :: (Qureg, Qubit, Qubit, Int) -> Circ ()+parseNodeRoot (a, root, even, n) = do+ comment_with_label "ENTER: parseNodeRoot" (a, root, even) ("a", "root", "even")+ with_ancilla_reg (n+1) $ \scratch -> do+ for n 1 (-1) $ \index -> do + with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ endfor+ with_controls (scratch.!(0) .==. 0) $ do {+ qnot_at root;+ qnot_at even+ }+ for 1 n 1 $ \index -> do + with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1))+ }+ endfor+ comment_with_label "EXIT: parseNodeRoot" (a, root, even) ("a", "root", "even")+ return ()+ +main = print_generic Preview circuit (qureg_shape (n+1), qubit, qubit) + where+ circuit (a, root, even) = parseNodeRoot (a, root, even, n)+ n = 4+
@@ -0,0 +1,22 @@+-- $ Test whether the quantum simulator works correctly on a global+-- phase gate.++import Quipper+import Quipper.Libraries.Simulation++-- | This function should compute a Not gate.+testcirc :: Qubit -> Circ Qubit+testcirc a = do+ hadamard_at a+ global_phase 1.0 `controlled` a+ hadamard_at a+ return a+ +main = do+ b <- run_generic_io d testcirc False+ putStrLn ("testcirc False = " ++ show b)+ b <- run_generic_io d testcirc True+ putStrLn ("testcirc True = " ++ show b)+ where+ d :: Double+ d = undefined
@@ -0,0 +1,139 @@++import Quipper++-- import other stuff+import Control.Monad (zipWithM_)++-- ======================================================================+-- ALGORITHM SPECIFIC CODE++{- the test circuit from Alex V. and Benoit's email. It looks like+this:++In Alex's notation: ++ H(a)+ c = meas(a)+ if c then+ X(b)+ else Y(b)++In circuit notation:++ a -H--Meas===x==o==|+ | |+ b -----------X--Y----++In QPL notation: +-} ++testcircuit :: (Qubit, Qubit) -> Circ Qubit+testcircuit (a,b) = do+ hadamard a+ c <- measure a+ with_controls (c .==. 1) $ do {+ gate_X_at b+ }+ with_controls (c .==. 0) $ do {+ gate_Y_at b+ }+ cdiscard c+ return b++-- Let's see if we can implement some parts of the Steane+-- code. Working from Alex V.'s notes.+++-- prepare the logical |+〉 state for the Steane code. This returns a list+-- of 7 qubits+plusState :: Circ [Qubit]+plusState = do+ -- prepare (a...g) in the state "00+0+++"+ [a,b,c,d,e,f,g] <- qinit_of_string "00+0+++"++ qnot_at a `controlled` c .==. 1+ qnot_at d `controlled` f .==. 1+ qnot_at b `controlled` g .==. 1+ qnot_at a `controlled` e .==. 1+ qnot_at d `controlled` g .==. 1+ qnot_at b `controlled` f .==. 1+ qnot_at a `controlled` g .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at d `controlled` e .==. 1+ + return [a,b,c,d,e,f,g]++-- prepare the logical |0〉 state for the Steane code+zeroState :: Circ [Qubit]+zeroState = do+ -- prepare (a...g) in the state "00+0+++"+ [a,b,c,d,e,f,g] <- qinit_of_string "++0+000"++ qnot_at c `controlled` a .==. 1+ qnot_at f `controlled` d .==. 1+ qnot_at g `controlled` b .==. 1+ qnot_at e `controlled` a .==. 1+ qnot_at g `controlled` d .==. 1+ qnot_at f `controlled` b .==. 1+ qnot_at g `controlled` a .==. 1+ qnot_at c `controlled` b .==. 1+ qnot_at e `controlled` d .==. 1+ + return [a,b,c,d,e,f,g]++preparePlus :: Circ ([Qubit], Bit)+preparePlus = do+ qs <- plusState+ vs <- plusState+ zipWithM_ (\q v -> qnot_at q `controlled` v .==. 1) qs vs+ measure <- mapM measure vs+ result <- cgate_and measure+ mapM_ cdiscard measure+ return (qs, result)++{-+-- this function operates on a 7-tuple of qubits, which are inputs and+-- outputs. The additional output Bit is 0 when the error correction+-- fails, else 1+preGateCorrection :: (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit,Qubit) -> Bit+preGateCorrection q = do+ result = cinit_bit False+ (a, av, result_a) <- preparePlus []+ with_controls (result_a .==. 1) $ do {+ (b, bv, result_b) <- prepareZero+ with_controls (result_b .==. 1) $ do {+ zRecover(q, a),+ xRecover(q, b),+ cnot result+ }+ with_controls (result_b .==. 0) $ do {+ .....+-}++ +-- ======================================================================+-- main functions (ugly, don't follow an "idiom" yet)++-- this is just a main function to print the circuit+main_testcircuit :: IO()+main_testcircuit =+ print_generic Preview testcircuit (qubit,qubit)++-- this is just a main function to print the circuit+main_plusState :: IO()+main_plusState =+ print_generic Preview plusState++-- this is just a main function to print the circuit+main_zeroState :: IO()+main_zeroState =+ print_generic Preview zeroState+ +-- this is just a main function to print the circuit+main_preparePlus :: IO()+main_preparePlus =+ print_generic Preview preparePlus+ +main = main_preparePlus++
@@ -0,0 +1,5 @@+import Quipper+import Quipper.Libraries.QFT++main :: IO ()+main = print_generic Preview qft_little_endian (replicate 5 qubit)
@@ -0,0 +1,64 @@+import Quipper+import Quipper.Libraries.Arith+import Quipper.Libraries.QFTAdd+import Quipper.Libraries.Simulation+import Quipper.Libraries.Unboxing++import System.Environment++------ Functions for testing the QFTAdd circuit --------++-- | Output a preview of the qft_add_in_place circuit for quantum integers of+-- the given size+print_qft_add :: Int -> IO ()+print_qft_add m = print_generic Preview qft_add_in_place (qdint_shape m) (qdint_shape m)++-- | Simulate the running of the qft_add_in_place circuit for the given IntM inputs+run_qft_add :: IntM -> IntM -> IO (IntM,IntM)+run_qft_add = run_generic_io (undefined :: Double) (unbox qft_add_in_place)++-- | A wrapper around 'run_qft_add' so that it can be used with standard Integer+-- arguments.+test_add :: Integer -> Integer -> IO Integer+test_add a b = if (a < 0) || (b < 0) then error "test_add: negative argument" else+ do+ let m = 2 + ceiling (log (fromInteger (a+b)) / log 2) -- a slight cheat to work out how many qubits to use+ let a' = intm m a+ let b' = intm m b+ (_,ab) <- run_qft_add a' b'+ return (fromIntegral ab)++-- | A datatype for the possible command line arguments+data Args = Usage | One Int | Two Integer Integer ++-- | A function to parse the command line arguments+parseArgs :: [String] -> Args+parseArgs [s1] = case reads s1 of+ [(x1,_)] -> One x1+ _ -> Usage+parseArgs [s1,s2] = case (reads s1,reads s2) of+ ([(x1,_)],[(x2,_)]) -> Two x1 x2+ _ -> Usage+parseArgs _ = Usage++-- | The main function calls either test_add or print_qft_add depending upon+-- command line arguments.+main :: IO ()+main = do+ args <- getArgs+ case parseArgs args of+ Usage -> usage+ One x -> print_qft_add x+ Two x1 x2 -> do+ res <- test_add x1 x2+ putStrLn (show x1 ++ " + " ++ show x2 ++ " = " ++ show res)++usage :: IO ()+usage = do+ name <- getProgName+ putStrLn ("usage: " ++ name ++ " num1 <num2>") + putStrLn " - one argument:"+ putStrLn " preview the circuit for quantum integers of that length"+ putStrLn " - two arguments:"+ putStrLn " simulate the circuit for adding the two numbers"+ putStrLn " (note that quantum simulation is not efficient)"
@@ -0,0 +1,15 @@++import Quipper+import Quipper.Libraries.Qram+import Quipper.Libraries.Arith++test_qram :: [Qubit] -> QDInt -> Circ ()+test_qram list index = do+ label (list,index) ("list","index")+ with_computed (indexed_access list index) $ \element -> do+ label element "element"+ hadamard_at element+++main :: IO ()+main = print_generic Preview test_qram (replicate 8 qubit) (qdint_shape 3)
@@ -0,0 +1,125 @@+import Quipper+import Quipper.Libraries.Simulation+import Quipper.Libraries.QuantumIf++-- ----------------------------------------------------------------------+-- * Testing quantum \"if then else\"++-- | A dummy value of type Double, to feed the type in the simulator+double :: Double+double = undefined++-- | A testing function that displays a circuit that tests the 'if_then_elseQ'+-- statement, and the results of running the circuit on various inputs.+if_test :: IO ()+if_test = do+ print_simple ASCII ifTest2+ print_simple Preview ifTest2+ res0 <- run_generic_io double ifTest2 (False,False,False)+ putStrLn (show res0)+ res1 <- run_generic_io double ifTest2 (False,False,True)+ putStrLn (show res1)+ res2 <- run_generic_io double ifTest2 (False,True,False)+ putStrLn (show res2)+ res3 <- run_generic_io double ifTest2 (False,True,True)+ putStrLn (show res3)+ res4 <- run_generic_io double ifTest2 (True,False,False)+ putStrLn (show res4)+ res5 <- run_generic_io double ifTest2 (True,False,True)+ putStrLn (show res5)+ res6 <- run_generic_io double ifTest2 (True,True,False)+ putStrLn (show res6)+ res7 <- run_generic_io double ifTest2 (True,True,True) + putStrLn (show res7)++-- | A test of the 'if_then_elseQ' function.+ifTest :: Circ (Qubit,Qubit,Qubit)+ifTest = do+ (q0,q1,q2,q3,q4,q5,q6) <- qinit (False,False,False,False,False,False,False)+ qnot_at q4+ if_then_elseQ (Or (A q0) (And (A q1) (Not (A q2))))+ ( --if q0 | (q1 & !q2)+ qnot_at q4+ )+ (+ if_then_elseQ (And (A q2) (A q3))+ ( --else if+ qnot_at q5 + )+ ( -- else+ qnot_at q6+ )+ )+ return (q4,q5,q6) ++-- | Another test of the 'if_then_elseQ' function.+ifTest2 :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit)+ifTest2 (l,p,d) = do+ ctrl <- qinit True+ (x,y) <- qinit (False,False)+ with_controls ctrl + (+ do + if_then_elseQ (Or (A l) (And (A p) (Not (A d))))+ ( --if l | (p & !d) + qnot_at x+ )+ ( -- else+ qnot_at y+ )+ )+ qdiscard (l,p,d)+ qterm True ctrl+ return (x,y)++-- | A simple test of the 'if_then_elseQ' function.+ifTest3 :: Qubit -> Circ (Qubit,Qubit)+ifTest3 q = do+ (q0,q1) <- qinit (False,False)+ if_then_elseQ (A q)+ (+ qnot_at q0+ )+ (+ qnot_at q1+ )+ qdiscard q+ return (q0,q1) ++-- | A small circuit for testing 'if_then_elseQinv' statements.+small_circ :: [Qubit] -> Circ ([Qubit],Qubit,Qubit)+small_circ qs = do+ (q1,q2) <- qinit (False,False)+ tempReg0 <- qinit (replicate (length qs) False)+ tempReg1 <- qinit (replicate (length qs) True)+ let boolean_statement = foldr1 (\x y -> And x y) (map A qs)+ let boolean_statement_out = Not boolean_statement+ if_then_elseQinv boolean_statement+ (+ do+ qnot_at q1+ swap (reverse tempReg0) (reverse qs)+ return ()+ )+ (+ do+ swap tempReg1 qs+ qnot_at q2+ ) boolean_statement_out+ return (qs,q1,q2) ++-- | Display the 'small_circ'.+print_small_circ :: IO ()+print_small_circ = print_generic Preview small_circ (replicate 4 qubit) ++-- | Simulate the 'small_circ'.+test_small_circ :: [Bool] -> IO ()+test_small_circ bs = do+ putStr (show bs ++ " -> ")+ res <- run_generic_io double small_circ bs+ putStrLn (show res)++-- | A main function.+main :: IO ()+main = test_small_circ [True,True,False]+
@@ -0,0 +1,13 @@+import Quipper++my_circuit :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+my_circuit (a,b) = do+ qnot_at a `controlled` b+ hadamard b `controlled` a+ return (a,b) + +rev_circuit :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+rev_circuit = reverse_simple my_circuit++main =+ print_simple Preview rev_circuit
@@ -0,0 +1,85 @@+-- | A test file to simulate various decompositions of the simple oracle circuit,+-- from the BWT algorithm.++import Quipper+import Quipper.Libraries.Simulation+import Quipper.Libraries.Decompose++-- import other Quipper stuff+import Quipper.Algorithms.BWT.Alternative+import Quipper.Utils.Auxiliary++-- | Extract the circuit from an oracle.+oracleCircuit :: Oracle -> Int -> Int -> Circ (Qubit,[Qubit])+oracleCircuit oracle color i = do+ input <- qinit (boollist_of_int_bh (m oracle) i)+ output <- qinit (boollist_of_int_bh (m oracle) 0)+ q <- qinit False+ oraclefun oracle color (input,output,q)+ return (q, output)+ +-- | Run the simple oracle with a given decomposition, and given inputs.+run_simple' :: GateBase -> Int -> Int -> IO (Bool,Int)+run_simple' gb color i = do (b,bs) <- run_generic_io (undefined :: Double) (decompose_generic gb (oracleCircuit oracle_simple color i))+ return (b, int_of_boollist_unsigned_bh bs)++-- | Run the simple oracle with a given decomposition, and given inputs, and print the result in a more readable manner.+run_simple :: GateBase -> Int -> Int -> IO ()+run_simple gb color i = do (b,bs) <- run_simple' gb color i+ if not b + then putStrLn (show i ++ " --( " ++ show color ++ " )--> " ++ show bs)+ else return ()++-- | Run the simple oracle with a given decomposition, mapped over all possible inputs.+main_run' :: GateBase -> IO ()+main_run' gb = mapM_ (\(x,y) -> run_simple gb x y) [(x,y) | y <- [0..31], x <- [0..3]]++-- | Run each decomposition of the oracle circuit and print out the resulting edges.+main_run :: IO ()+main_run = do putStrLn "Logical"+ main_run' Logical+ putStrLn "Toffoli"+ main_run' Toffoli+ putStrLn "Binary"+ main_run' Binary ++-- | Simumlate the simple oracle with a given decomposition, and given inputs.+sim_simple' :: GateBase -> Int -> Int -> ProbabilityDistribution Double (Bool,Int)+sim_simple' gb color i = do (b,bs) <- sim_generic undefined (decompose_generic gb (oracleCircuit oracle_simple color i))+ return (b, int_of_boollist_unsigned_bh bs)++-- | Simulate the simple oracle with a given decomposition,+-- and given inputs, and print the result in a more readable manner.+sim_simple :: GateBase -> Int -> Int -> ProbabilityDistribution Double (IO ())+sim_simple gb color i = do (b,bs) <- sim_simple' gb color i+ if not b + then return $ putStr (show i ++ " --( " ++ show color ++ " )--> " ++ show bs)+ else Vector [(return (),0.0)]++sequenceP :: ProbabilityDistribution Double (IO ()) -> IO ()+sequenceP (Vector []) = return ()+sequenceP (Vector ((io,prob):ps)) = do if prob /= 0.0 then do io+ putStrLn (" - " ++ show prob)+ else return ()+ sequenceP (Vector ps) ++-- | Simulate the simple oracle with a given decomposition, mapped over all possible inputs.+main_sim' :: GateBase -> IO ()+main_sim' gb = mapM_ (\(x,y) -> sequenceP (sim_simple gb x y)) [(x,y) | y <- [0..31], x <- [0..3]]++main_sim'' :: GateBase -> Int -> Int -> IO ()+main_sim'' gb x y = sequenceP (sim_simple gb x y)++-- | Simulate each decomposition of the oracle circuit and print out the resulting edges.+main_sim :: IO ()+main_sim = do putStrLn "Logical"+ main_sim' Logical+ putStrLn "Toffoli"+ main_sim' Toffoli+ putStrLn "Binary"+ main_sim' Binary ++main :: IO ()+main = do main_run+ main_sim+
@@ -0,0 +1,30 @@+import Quipper+import Quipper.Libraries.Simulation+import System.Random++circuit :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+circuit (q,r) = do+ with_computed code $ \x -> do+ qnot r `controlled` [r,x]+ hadamard r+ return (q,r)++ where+ code = do+ s <- cinit False+ s <- prepare s+ hadamard q+ qnot s `controlled` q+ ++circuit2 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+circuit2 (s,q,r) = do+ circuit (q,r) `controlled` s+ return (s,q,r)++main =+ print_simple Preview circuit2+ +main2 = do+ g <- newStdGen+ print $ run_generic g (0.0 :: Double) circuit2 (True,True,True)
@@ -0,0 +1,106 @@+-- | Some demos for "Quipper.Libraries.Synthesis".++import Quipper+import Quipper.Libraries.Synthesis++import Quantum.Synthesis.Ring+import Quantum.Synthesis.Matrix+import Quantum.Synthesis.MultiQubitSynthesis++import System.Random++-- ----------------------------------------------------------------------+-- * Some demos for Quipper.Libraries.Synthesis++-- | Import a compressed Clifford+/T/ operator as a Quipper circuit.+main1 :: IO ()+main1 = do+ print_simple Preview (exact_synthesis1 (0x1d00d27a0188b095b8cdd4ead9a244198d8b22e :: Integer))+ +-- | Exact synthesis of a Clifford+/T/ circuit from an exact matrix+-- representation.+main2 :: IO ()+main2 = do+ print_simple Preview (exact_synthesis1 op)+ where+ op :: Matrix Two Two DOmega+ op = roothalf^4 * matrix2x2 ( 1 - 2*roottwo, 2 + roottwo - i )+ ( -2 - roottwo - i, 1 - 2*roottwo )++-- | Exact synthesis of a multi-qubit Clifford+/T/ circuit from an+-- exact matrix representation.+main3 :: IO ()+main3 = do+ print_generic Preview (exact_synthesis_alt op) [qubit, qubit]+ where+ op :: Matrix Four Four DOmega+ op = matrix4x4 ( 1, 0, 0, 0 )+ ( 0, -s, s, 0 )+ ( 0, 0, 0, 1 )+ ( 0, s, s, 0 ) + s = roothalf+ +-- | Exact synthesis of a multi-qubit Clifford+/T/ circuit from an+-- exact matrix representation.+main3a :: IO ()+main3a = do+ print_generic Preview (exact_synthesis_alt op) [qubit, qubit, qubit]+ where+ op :: Matrix Eight Eight DOmega+ op = matrix [[ 1, 0, 0, 0, 0, 0, 0, 0 ],+ [ 0, s, -s, 0, 0, 0, 0, 0 ],+ [ 0, 0, 0, 1, 0, 0, 0, 0 ],+ [ 0, s, s, 0, 0, 0, 0, 0 ],+ [ 0, 0, 0, 0, 1, 0, 0, 0 ],+ [ 0, 0, 0, 0, 0, 1, 0, 0 ],+ [ 0, 0, 0, 0, 0, 0, 0, 1 ],+ [ 0, 0, 0, 0, 0, 0, 1, 0 ]] + s = roothalf+ +-- | Approximate synthesis of a /z/-rotation as a Clifford+/T/ circuit.+-- Angle θ = π\/128, precision ε = 10[sup −30].+main4 :: IO ()+main4 = do+ g <- newStdGen -- a source of randomness+ print_simple Preview (approximate_synthesis_zrot prec (pi/128) g)+ where+ prec = 30 * digits++-- | Approximate synthesis of a global phase. +-- Angle α = π\/128, precision ε = 10[sup −30].+main5 :: IO ()+main5 = do+ g <- newStdGen -- a source of randomness+ print_simple Preview (approximate_synthesis_phase True prec (pi/128) g)+ where + prec = 30 * digits++-- | Approximate synthesis of an arbitrary single-qubit operator,+-- given by Euler angles. Precision ε = 2[sup −50].+main6 :: IO ()+main6 = do+ g <- newStdGen -- a source of randomness+ let circ = approximate_synthesis_euler True prec (alpha, beta, gamma, delta) g+ print_simple Preview circ+ where+ prec = 50 * bits+ alpha = 0.1 * pi+ beta = 0.2 * pi+ gamma = 0.5 * pi+ delta = -0.6 * pi+ +-- | Approximate synthesis of an arbitrary single-qubit operator,+-- given as a matrix. The matrix is given in an exact notation.+-- Precision ε = 10[sup −10].+main7 :: IO ()+main7 = do+ g <- newStdGen -- a source of randomness+ let circ = approximate_synthesis_u2 True prec op g+ print_simple Preview circ+ where+ prec = 10 * digits+ op = matrix2x2 ( 0.6, 0.8*i )+ (-0.8, 0.6*i )++-- | Run any of the above main functions:+main = main3a
@@ -0,0 +1,55 @@+import Quipper++plus_minus :: Bool -> Circ Qubit+plus_minus b = do+ q <- qinit b+ q <- hadamard q+ return q++share :: Qubit -> Circ (Qubit, Qubit)+share a = do+ b <- qinit False+ b <- qnot b `controlled` a+ return (a,b)++bell00 :: Circ (Qubit, Qubit)+bell00 = do+ a <- plus_minus False+ (a,b) <- share a+ return (a,b)++alice :: Qubit -> Qubit -> Circ (Bit,Bit)+alice q a = do+ a <- qnot a `controlled` q+ q <- hadamard q+ (x,y) <- measure (q,a)+ return (x,y)++bob :: Qubit -> (Bit,Bit) -> Circ Qubit+bob b (x,y) = do+ b <- gate_X b `controlled` y+ b <- gate_Z b `controlled` x+ cdiscard (x,y)+ return b++teleport :: Qubit -> Circ Qubit+teleport q = do+ (a,b) <- bell00+ (x,y) <- alice q a+ b <- bob b (x,y)+ return b++-- ----------------------------------------------------------------------+-- main functions++main_alice =+ print_simple Preview alice++main_bob =+ print_simple Preview bob++main_teleport =+ print_simple Preview teleport++main = main_teleport+
@@ -0,0 +1,170 @@+import Quipper+import Quipper.Libraries.Simulation++import System.Random+import System.Environment+import System.CPUTime++plus_minus :: (QShape a qa ca) => a -> Circ qa+plus_minus a = do + qs <- qinit a+ qs <- mapUnary hadamard qs+ return qs++share :: (QShape a qa ca) => qa -> Circ (qa, qa)+share qa = do + qb <- qinit (qc_false qa)+ (qb, qa) <- mapBinary controlled_not qb qa+ return (qa, qb)++bell00 :: (QShape a qa ca) => a -> Circ (qa, qa)+bell00 shape = do + qa <- plus_minus shape+ (qa, qb) <- share qa+ return (qa, qb)++alice :: (QShape a qa ca) => qa -> qa -> Circ (ca,ca)+alice q a = do + (a, q) <- mapBinary controlled_not a q+ q <- mapUnary hadamard q+ (x,y) <- measure (q,a)+ return (x,y)++bob :: (QShape a qa ca) => qa -> (ca,ca) -> Circ qa+bob b (x,y) = do+ (b, y) <- mapBinary_c controlled_X b y+ (b, x) <- mapBinary_c controlled_Z b x+ cdiscard (x,y)+ return b+ where+ controlled_X b x = do+ gate_X b `controlled` x+ return (b,x)+ + controlled_Z b x = do+ gate_Z b `controlled` x+ return (b,x)+ +teleport :: (QData qa) => qa -> Circ qa+teleport q = do+ (a,b) <- bell00 (qc_false q)+ (x,y) <- alice q a+ b <- bob b (x,y)+ return b++teleport_labeled :: (QData qa) => qa -> Circ qa+teleport_labeled q = do+ comment_with_label "ENTER: teleport_labeled" q "q"+ comment "ENTER: bell00"+ (a,b) <- bell00 (qc_false q)+ comment_with_label "EXIT: bell00" (a,b) ("a","b")+ comment "ENTER: alice"+ (x,y) <- alice q a+ comment_with_label "EXIT: alice" (x,y) ("x","y")+ comment "ENTER: bob"+ b <- bob b (x,y)+ comment_with_label "EXIT: bob" b "b"+ comment "EXIT: teleport_labeled"+ return b++-- | A test that should help see how many qubits we can simulate+test_teleport :: [Bool] -> IO [Bool]+test_teleport = run_clifford_generic teleport++data What = Sim | Circ | Usage deriving Eq++-- | The main method deals with command line arguments, and timing of the simulation+main :: IO ()+main = do+ args <- getArgs+ if (length args /= 2) then usage else do+ let arg1 = head args+ let flag = case arg1 of+ "--sim" -> Sim+ "--circ" -> Circ + _ -> Usage+ if (flag == Usage) then usage else do + let arg = head (tail args)+ case reads arg of+ [(n,_)] -> do+ if (n < 0) then usage else do+ if (flag == Circ) then print_generic Preview teleport_labeled (replicate n qubit) else do+ input <- randomBools n+ putStrLn ("Input: " ++ show input)+ start <- getCPUTime+ output <- test_teleport input+ end <- getCPUTime+ putStrLn ("Output: " ++ show output)+ let time = end - start+ putStrLn ("Time: (" ++ show time ++ ")")+ show_time time+ _ -> usage++-- | Produce the given number of random boolean values+randomBools :: Int -> IO [Bool]+randomBools 0 = return []+randomBools n = do+ b <- randomIO+ bs <- randomBools (n-1)+ return (b:bs)++-- | Give a usage message if not being run from GHCI+usage :: IO ()+usage = do+ name <- getProgName+ if name == "<interactive>" then prompt else do+ putStrLn ("usage: " ++ name ++ " flag num_qubits")+ putStrLn (" where flag = --sim or --circ") ++-- | If we're in GHCI then we can prompt for the number of qubits to teleport+prompt :: IO ()+prompt = do+ putStrLn "Enter flag (--sim or --circ): "+ f <- getLine+ putStrLn "Enter number of qubits: "+ n <- getLine+ withArgs [f,n] main ++-- | Display an integer representing pico-seconds in a more readable format+show_time :: Integer -> IO ()+show_time t = case range t of+ Pico -> putStrLn (show t ++ " " ++ show Pico ++ ".")+ r -> do+ putStr (show (div t (ps' r)) ++ " " ++ show r ++ ", ")+ show_time (rem t (ps' r))++-- | Helper data-type for show_time function+data Range = Pico | Nano | Micro | Milli | Seconds | Minutes | Hours | Days+ deriving Eq++instance Show Range where+ show Pico = "picoseconds"+ show Nano = "nanoseconds"+ show Micro = "microseconds"+ show Milli = "milliseconds"+ show Seconds = "seconds"+ show Minutes = "minutes"+ show Hours = "hours"+ show Days = "days"++-- | Helper function for show_time function+ps' :: Range -> Integer+ps' Pico = 1+ps' Nano = 10^3 * ps' Pico+ps' Micro = 10^3 * ps' Nano+ps' Milli = 10^3 * ps' Micro+ps' Seconds = 10^3 * ps' Milli +ps' Minutes = 60 * ps' Seconds+ps' Hours = 60 * ps' Minutes+ps' Days = 24 * ps' Hours++-- | Helper function for show_time function+range :: Integer -> Range+range t = + if (t < 10^3) then Pico else+ if (t < 10^6) then Nano else+ if (t < 10^9) then Micro else+ if (t < 10^12) then Milli else+ if (t < 60*(10^12)) then Seconds else+ if (t < 60*60*(10^12)) then Minutes else+ if (t < 24*60*60*(10^12)) then Hours else Days
@@ -0,0 +1,67 @@+-- | This file illustrates the most basic use of Template Haskell.++import Quipper++-- | A classical implementation of some boolean function.+build_circuit+example1 :: Bool -> Bool -> Bool+example1 a b = (a && b) || not a++-- $ The keyword \"build_circuit\" causes an equivalent quantum function+-- to be built automatically. It will have the following name and+-- type:+-- +-- > template_example1 :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))+-- +-- The various nested 'Circ' applications are an artifact, and can and+-- should be removed using the 'unpack' operator:+-- +-- > (unpack template_example1) :: Qubit -> Qubit -> Circ Qubit++-- | This main function prints the circuit generated from 'example1'.+main1 :: IO ()+main1 =+ print_simple Preview (unpack template_example1)++-- | Here is some other boolean function. We do not use the+-- \"build_circuit\" keyword.+fake :: Bool -> Bool+fake b = not b++-- $ Suppose we want to use the function 'fake' as a subroutine+-- elsewhere:+{-+build_circuit+example2 :: Bool -> Bool -> Bool+example2 a b = fake (a && b) || not a+-}++-- | This will fail, because build_circuit does not know how to+-- translate the 'fake' function. +-- +-- We can fix this by manually providing a template. This is useful in+-- two situations:+-- +-- 1. To provide a template for a Haskell built-in function;+-- +-- 2. To provide a more efficient template for some function than the+-- one build_circuit can build automatically.+template_fake :: Circ (Qubit -> Circ Qubit)+template_fake = return f where+ f q = do+ qnot_at q+ return q++-- | Now that a template for 'fake' has been defined, the definition+-- of 'example2' works:+build_circuit+example2 :: Bool -> Bool -> Bool+example2 a b = fake (a && b) || not a+++-- | This main function prints the circuit generated from 'example2'. +main2 :: IO ()+main2 =+ print_simple Preview (unpack template_example2)++main = main2
@@ -0,0 +1,31 @@+import Quipper++circuit :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+circuit (a, b, c) = do+ qnot_at a `controlled` [b]+ qnot_at b `controlled` [c]+ hadamard c `controlled` [a,b]+ return (a, b, c)++hadamard2 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+hadamard2 (h, a, b) = do+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard h `controlled` [c]+ qnot_at c `controlled` [a, b]+ return (h, a, b)++example :: (Qubit, Qubit, Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit, Qubit, Qubit)+example (a, b, c, d, e) = do+ circuit (a, b, c)+ circuit (b, c, a)+ with_controls (d .==. 1 .&&. e .==. 0) $ do {+ circuit (a, b, c);+ circuit (b, c, a);+ }+ circuit (a, b, c)+ circuit (b, c, a)+ return (a, b, c, d, e)++main =+ print_simple Preview example
@@ -0,0 +1,79 @@+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}++-- $+-- Generate some circuits for the slides in the PI presentation.++import Quipper++example_H3 :: Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example_H3 h a b c = do+ with_ancilla $ \d -> do+ with_ancilla $ \e -> do+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ hadamard_at h `controlled` e .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1++example_H3' :: Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example_H3' h a b c d e = do+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ hadamard_at h `controlled` e .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1++example :: Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example a b c d = do+ example_H3 a b c d+ qnot_at a `controlled` b .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at c `controlled` d .==. 1 .&&. a .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at a `controlled` b .==. 1+ example_H3 b c d a++example' :: Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example' a b c d anc1 anc2 = do+ example_H3' a b c d anc1 anc2+ qnot_at a `controlled` b .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at c `controlled` d .==. 1 .&&. a .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at a `controlled` b .==. 1+ example_H3' b c d a anc1 anc2+++main3 =+ print_generic Preview example qubit qubit qubit qubit++main =+ print_simple Preview example'++ec1 :: Qubit -> Circ [Qubit]+ec1 a = do+ b <- qinit False+ c <- qinit False+ qmultinot_at (b,c) `controlled` a .==. 1+ return [a,b,c]++corr :: [Qubit] -> Circ Qubit+corr [a,b,c] = do+ qmultinot_at (a,c) `controlled` b .==. 1+ (a',c') <- measure (a,c)+ qnot_at b `controlled` a' .==. 1 .&&. c' .==. 1+ cdiscard (a',c')+ return b++ec2 :: [Qubit] -> Circ [Qubit]+ec2 [a,b,c] = do+ [a1,a2,a3] <- ec1 a+ [b1,b2,b3] <- ec1 b+ [c1,c2,c3] <- ec1 c+ x1 <- corr [a1,b1,c1]+ x2 <- corr [a2,b2,c2]+ x3 <- corr [a3,b3,c3]+ return [x1,x2,x3]+++main4 = print_generic Preview ec2 [qubit, qubit, qubit]
@@ -0,0 +1,36 @@+import Quipper+import Quipper.Libraries.Qureg+import Quipper.Libraries.Decompose++import Quipper.Algorithms.BWT.Definitions++-- | Algorithm 3. @timestep (a, b, r, dt, m)@: Apply the+-- time step /dt/ to (/a/,/b/,/r/). Here /a/ and /b/ are /m/-qubit+-- registers while /r/ is a single qubit.+timestep :: (Qureg, Qureg, Qubit, Timestep, Int) -> Circ ()+timestep (a, b, r, dt, m) = do+ comment_with_label "ENTER: timestep" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ for 0 (m-1) 1 $ \i -> do+ wGate (a.!(i), b.!(i))+ endfor+ for 0 (m-1) 1 $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ controlledExpGate (dt, r, h)+ for (m-1) 0 (-1) $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ for (m-1) 0 (-1) $ \i -> do+ wGateInverse (a.!(i), b.!(i))+ endfor+ comment_with_label "EXIT: timestep" (a,b,r) ("a","b","r")+ return ()++main = print_generic Preview (decompose_generic Binary circuit) (nodeshape, nodeshape, qubit)+ where+ circuit (a, b, r) = timestep (a, b, r, dt, m)+ n = 4+ m = n+2+ dt = pi/180+ nodeshape = qureg_shape m
@@ -0,0 +1,34 @@+import Quipper+import Quipper.Libraries.Qureg+import Quipper.Algorithms.BWT.Definitions++-- | Algorithm 3. @timestep (a, b, r, dt, m)@: Apply the+-- time step /dt/ to (/a/,/b/,/r/). Here /a/ and /b/ are /m/-qubit+-- registers while /r/ is a single qubit.+timestep :: (Qureg, Qureg, Qubit, Timestep, Int) -> Circ ()+timestep (a, b, r, dt, m) = do+ comment_with_label "ENTER: timestep" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ for 0 (m-1) 1 $ \i -> do+ wGate (a.!(i), b.!(i))+ endfor+ for 0 (m-1) 1 $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ controlledExpGate (dt, r, h)+ for (m-1) 0 (-1) $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ for (m-1) 0 (-1) $ \i -> do+ wGateInverse (a.!(i), b.!(i))+ endfor+ comment_with_label "EXIT: timestep" (a,b,r) ("a","b","r")+ return ()++main = print_generic Preview circuit (nodeshape, nodeshape, qubit)+ where+ circuit (a, b, r) = timestep (a, b, r, dt, m)+ n = 4+ m = n+2+ dt = pi/180+ nodeshape = qureg_shape m
@@ -0,0 +1,23 @@+import Quipper+ +mytransformer :: Transformer Circ Qubit Bit+mytransformer (T_QGate "swap" 2 0 _ ncf f) = f $+ \[q0, q1] [] ctrls -> do+ without_controls_if ncf $ do+ with_controls ctrls $ do+ qnot_at q0 `controlled` q1+ qnot_at q1 `controlled` q0+ qnot_at q0 `controlled` q1+ return ([q0, q1], [], ctrls)+mytransformer g = identity_transformer g++mycirc a b c d = do+ swap_at a b+ hadamard_at b+ swap_at b c `controlled` [a, d]+ hadamard_at c+ swap_at c d++mycirc2 = transform_generic mytransformer mycirc++main = print_simple Preview mycirc2
@@ -0,0 +1,40 @@+import Quipper++crazy :: (QData a, QCData b) => (a -> Circ b) -> (a -> Circ (a,b))+crazy f a = do+ mapUnary hadamard a+ y <- with_computed (f a) $ \b -> do+ b' <- qc_copy b+ return (a,b')+ return y++circuit :: [Qubit] -> Circ ([Qubit], [Qubit])+circuit qs = do+ y <- with_computed values $ \values -> do+ qc_copy values+ return (qs, y)+ + where+ values = do+ mapUnary hadamard qs+ a <- qinit True+ b <- qinit False+ qnot_at a `controlled` qs+ qnot_at b `controlled` qs .==. [0,0..]+ c <- qinit False+ qnot_at c `controlled` [a,b]+ qnot_at b `controlled` qs .==. [0,0..]+ qnot_at a `controlled` qs+ qterm False b + qterm True a+ return (c:qs)++circuit2 :: [Qubit] -> Circ ([Qubit], ([Qubit], [Qubit]))+circuit2 = crazy circuit++circuit3 :: [Qubit] -> Circ ([Qubit], ([Qubit], ([Qubit], [Qubit])))+circuit3 = crazy circuit2++circuit4 = crazy circuit3++main = print_generic Preview circuit4 (replicate 5 qubit)
@@ -0,0 +1,15 @@+{-# LANGUAGE CPP #-}++import Distribution.Simple+import Quipper.Distribution.Preprocessor++-- The following is needed because of an incompatible change in Cabal 2.+#if MIN_VERSION_Cabal(2,0,0)+wrap x = \_ _ _ -> x+#else+wrap x = \_ _ -> x+#endif++main = defaultMainWithHooks simpleUserHooks {+ hookedPreProcessors = [("hs", wrap ppQuipper)]+ }
@@ -0,0 +1,14 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/And_gate.hs" #-}+import Quipper++and_gate :: (Qubit, Qubit) -> Circ (Qubit)+and_gate (a, b) = do+ c <- qinit False+ qnot_at c `controlled` [a, b]+ return c++main =+ print_simple Preview and_gate
@@ -0,0 +1,24 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/And_list.hs" #-}+import Quipper++and_gate :: (Qubit, Qubit) -> Circ (Qubit)+and_gate (a, b) = do+ c <- qinit False+ qnot_at c `controlled` [a, b]+ return c++and_list :: [Qubit] -> Circ Qubit+and_list [] = do+ c <- qinit True+ return c+and_list [q] = do+ return q+and_list (q:t) = do+ d <- and_list t+ e <- and_gate (d, q)+ return e++main = print_generic Preview and_list (replicate 10 qubit)
@@ -0,0 +1,30 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/And_rev.hs" #-}+import Quipper++and_gate :: (Qubit, Qubit) -> Circ (Qubit)+and_gate (a, b) = do+ c <- qinit False+ qnot_at c `controlled` [a, b]+ return c++and_list :: [Qubit] -> Circ Qubit+and_list [] = do+ c <- qinit True+ return c+and_list [q] = do+ return q+and_list (q:t) = do+ d <- and_list t+ e <- and_gate (d, q)+ return e++and_rev :: ([Qubit], Qubit) -> Circ ([Qubit], Qubit)+and_rev = classical_to_reversible and_list++main =+ print_generic Preview and_rev (replicate 10 qubit, qubit)++
@@ -0,0 +1,17 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Arith.hs" #-}+import Quipper+import Quipper.Libraries.Arith++main :: IO ()+main = print_generic Preview labelled_add (qdint_shape 3) (qdint_shape 3)+++labelled_add :: QDInt -> QDInt -> Circ (QDInt, QDInt,QDInt)+labelled_add x y = do+ label (x,y) ("x","y")+ xy <- q_add x y+ label xy ("x","y","x+y")+ return xy
@@ -0,0 +1,116 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Box.hs" #-}+import Quipper+import Quipper.Libraries.Unboxing++main :: IO ()+main = do+ print_generic Preview boxed_unboxed (replicate 5 qubit) (replicate 5 qubit)+ --print_simple Preview boxed_unboxed2+ --print_simple Preview boxed_unboxed3+ --print_simple Preview boxed_unboxed4++sub_notboxed :: [Qubit] -> Circ [Qubit]+sub_notboxed [] = return []+sub_notboxed [a] = return [a]+sub_notboxed (a:(b:cs)) = do+ a' <- hadamard a `controlled` b+ bcs' <- sub_notboxed (b:cs)+ return (bcs' ++ [a'])++sub_boxed :: [Qubit] -> Circ [Qubit]+sub_boxed = box "sub" sub_notboxed++my_circuit :: ([Qubit] -> Circ [Qubit]) -> [Qubit] -> [Qubit] -> Circ ([Qubit],[Qubit])+my_circuit sub as bs = do+ comment_with_label "ENTER: my_circuit" (as,bs) ("a","b")+ as' <- sub (reverse as) `controlled` (head bs)+ label (as',bs) ("a","b")+ bs' <- sub bs + label (as',bs') ("a","b")+ as'' <- reverse_generic_endo sub (reverse as') `controlled` (head bs')+ comment_with_label "EXIT: my_circuit" (as'',bs') ("a","b")+ return (as'',bs')++boxed_unboxed :: [Qubit] -> [Qubit] -> Circ ([Qubit],[Qubit])+boxed_unboxed as bs = do+ label (as,bs) ("a","b")+ (as,bs) <- my_circuit sub_notboxed as bs+ label (as,bs) ("a","b")+ (as,bs) <- my_circuit sub_boxed as bs+ label (as,bs) ("a","b")+ (as,bs) <- unbox (my_circuit sub_boxed) as bs+ label (as,bs) ("a","b")+ return (as,bs)++my_subroutine2 :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+my_subroutine2 (a,b,c) = do+ qnot_at c `controlled` [a,b]+ return (a,b,c)++sub2 :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+sub2 = box "tof" my_subroutine2++my_subroutine2' :: (Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit)+my_subroutine2' (a,b,c,d) = do+ (b',c',d') <- sub2 (b,c,d) `controlled` a+ return (a,b',c',d')++sub2' :: (Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit)+sub2' = box "ss" my_subroutine2'++my_circuit2 :: (Qubit,Qubit,Qubit,Qubit) -> (Qubit,Qubit,Qubit,Qubit) -> Circ ((Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit))+my_circuit2 as bs = do+ (a1,a2,a3,a4) <- sub2' as+ (b1,b2,b3,b4) <- sub2' bs + return ((a1,a2,a3,a4),(b1,b2,b3,b4))++boxed_unboxed2 :: (Qubit,Qubit,Qubit,Qubit) -> (Qubit,Qubit,Qubit,Qubit) -> Circ ((Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit))+boxed_unboxed2 as bs = do+ (as',bs') <- my_circuit2 as bs+ (as'',bs'') <- (unbox my_circuit2) as' bs'+ (unbox (unbox my_circuit2)) as'' bs''++my_subroutine3 :: (Qubit,Qubit,Qubit) -> Circ Qubit+my_subroutine3 (a,b,c) = do+ qdiscard (c,a)+ return b++sub3 :: (Qubit,Qubit,Qubit) -> Circ Qubit+sub3 = box "term" my_subroutine3++my_circuit3 :: (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit)+my_circuit3 (a,b,c,d,e,f) = do+ b' <- sub3 (a,b,c)+ e' <- sub3 (d,e,f)+ qnot_at e' `controlled` b' + return (b',e')++boxed_unboxed3 :: ((Qubit,Qubit,Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit)) -> Circ (Qubit,Qubit)+boxed_unboxed3 ((a,b,c,d,e,f),(c',d',e',f')) = do+ (a',b') <- my_circuit3 (a,b,c,d,e,f)+ (unbox my_circuit3) (a',b',c',d',e',f')++my_subroutine4 :: Qubit -> Circ (Qubit,Qubit,Qubit)+my_subroutine4 a = do+ (b,c) <- qinit (False,False)+ return (a,b,c)++sub4 :: Qubit -> Circ (Qubit,Qubit,Qubit)+sub4 = box "init" my_subroutine4++my_circuit4 :: (Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit)+my_circuit4 (a,b) = do+ (a',c,d) <- sub4 a + (b',e,f) <- sub4 b+ return (a',b',c,d,e,f)++boxed_unboxed4 :: (Qubit,Qubit) -> Circ ((Qubit,Qubit,Qubit,Qubit),(Qubit,Qubit,Qubit,Qubit,Qubit,Qubit))+boxed_unboxed4 (a,b) = do+ (a',b',c,d,e,f) <- my_circuit4 (a,b)+ (a'',b'',g,h,i,j) <- unbox my_circuit4 (a',b')+ return ((c,d,e,f),(a'',b'',g,h,i,j))++
@@ -0,0 +1,40 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/BoxExample.hs" #-}+import Quipper++-- Unboxed version of subroutine+my_sub :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+my_sub (a,b,c) = do+ hadamard_at a `controlled` b+ hadamard_at a `controlled` c+ hadamard_at b `controlled` c+ return (a,b,c)+ +-- Boxed version of subroutine+boxed_sub :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+boxed_sub = box "my_sub" my_sub++-- Unboxed version of circuit+my_circuit :: [Qubit] -> Circ [Qubit]+my_circuit [] = return []+my_circuit [a] = return [a]+my_circuit [a,b] = return [a,b]+my_circuit (a:b:c:rest) = do+ (a,b,c) <- my_sub (a,b,c)+ x <- my_circuit (b:c:rest)+ return (a:x)++-- Boxed version of circuit+my_circuit_boxed :: [Qubit] -> Circ [Qubit]+my_circuit_boxed [] = return []+my_circuit_boxed [a] = return [a]+my_circuit_boxed [a,b] = return [a,b]+my_circuit_boxed (a:b:c:rest) = do+ (a,b,c) <- boxed_sub (a,b,c)+ x <- my_circuit_boxed (b:c:rest)+ return (a:x)++main = do+ print_generic Preview my_circuit_boxed (replicate 6 qubit)
@@ -0,0 +1,16 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Classical.hs" #-}+import Quipper++circuit :: (Bit, Qubit) -> Circ (Qubit, Qubit)+circuit (b,q) = do+ qnot_at q `controlled` b+ r <- prepare b+ gate_W_at q r+ return (q,r)+ +main = + print_simple Preview circuit+
@@ -0,0 +1,29 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Comments.hs" #-}+import Quipper++example1 :: (Qubit,Qubit,[Qubit]) -> Circ (Qubit,Qubit,[Qubit])+example1 (q, a, b) = do+ comment_with_label "Start of example 1" (q,a,b) ("q","a","b")+ hadamard a+ qnot_at a `controlled` b+ hadamard q `controlled` a+ qnot_at a `controlled` b+ hadamard a+ comment "End of example 1"+ return (q, a, b)++example3 :: (Qubit,Qubit,[Qubit],Qubit,Qubit) -> Circ (Qubit,Qubit,[Qubit],Qubit,Qubit)+example3 (q, a, b, d, e) = do+ comment_with_label "Start of example 3" (q,a,b,d,e) ("q","a","b","d","e")+ example1 (q, a, b)+ with_controls (d .==. 0 .&&. e .==. 1) $ do+ example1 (q, a, b)+ example1 (q, a, b)+ example1 (q, a, b)+ comment "End of example 3"+ return (q, a, b, d, e)++main = print_generic Preview example3 (qubit, qubit, replicate 3 qubit, qubit, qubit)
@@ -0,0 +1,67 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/CountAccess.hs" #-}+-- | Consider the following problem, suggested by Dmitry Maslov: Input+-- a list of bits. Let /i/ be the weight of the list, i.e., the number+-- of \"1\" bits in the list. Output the /i/th element, where elements+-- are counted from 0 and we wrap around cyclically if /i/ equals the+-- length of the list.++import Quipper+import Quipper.Libraries.Arith+import Quipper.Libraries.Qram++import Prelude hiding (truncate)++-- | Figure out how many bits are needed to store a given integer. +hibit :: Int -> Int+hibit 0 = 0+hibit n = 1 + hibit (n `div` 2)++-- | @'truncate' n q@: Input a classical integer /n/ and a quantum+-- integer /q/. Output /0/ if /q/=/n/, and /q/ otherwise. For the+-- problem at hand, this is cheaper than full modular arithmetic. +truncate :: IntM -> QDInt -> Circ QDInt+truncate n q = do+ q' <- qc_copy q+ with_controls (q .==. n) $ do+ controlled_not q' q+ return q'++-- | Input a list of qubits and return its weight.+weight :: [Qubit] -> Circ QDInt+weight qs = q where+ len = length qs+ bits = hibit len+ zero = intm bits 0+ q = do+ q <- qinit zero+ q <- aux qs q+ q1 <- truncate (intm bits (toInteger len)) q+ return q1++ aux [] q = return q+ aux (h:t) q = do+ q <- q_increment q `controlled` h+ q <- aux t q+ return q++-- | Input a list of qubits, and output the /i/th qubit, where /i/ is+-- the weight of the list.+countshift :: [Qubit] -> Circ Qubit+countshift qs = do+ q <- weight qs+ a <- indexed_access qs q+ return a++-- | Reversible version of 'countshift'. +countshift_rev :: [Qubit] -> Circ ([Qubit], Qubit)+countshift_rev qs = do+ b <- with_computed (countshift qs) $ \a -> do+ qc_copy a+ return (qs, b)++-- | A main function to print the circuit.+main = + print_generic Preview countshift_rev (replicate 7 qubit)
@@ -0,0 +1,27 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Decompose_test.hs" #-}+import Quipper+import Quipper.Libraries.Decompose++toffoli :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+toffoli (q1,q2,q3) = do+ qnot_at q3 `controlled` (q1,q2)+ return (q1,q2,q3)++boxed :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit)+boxed = box "Toffoli" toffoli+++tof :: (Qubit,Qubit,Qubit,Qubit,Qubit) -> Circ ()+tof (q1,q2,q3,q4,q5) = do+ boxed (q3,q4,q5) `controlled` (q1,q2)+ return ()+ +main :: IO ()+main = do+ print_simple Preview tof+ print_simple Preview (decompose_generic Logical tof)+ print_simple Preview (decompose_generic Toffoli tof)+ print_simple Preview (decompose_generic Binary tof)
@@ -0,0 +1,27 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/DynamicLifting.hs" #-}+-- Test the dynamic lifting feature. ++import Quipper++-- | A circuit in which some future gates depend on a prior measurement.+circuit :: Qubit -> Qubit -> Circ Qubit+circuit a b = do+ qnot_at a `controlled` b+ m <- measure a+ bool <- dynamic_lift m+ if bool == 0 then+ do+ hadamard_at b+ return b+ else+ do+ c <- qinit False+ qnot_at c `controlled` b+ qdiscard b+ return c++main = do+ print_simple ASCII circuit
@@ -0,0 +1,32 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/ErrorCircuit.hs" #-}+import Quipper+import Quipper.Libraries.Decompose++-- Outputs a partially undefined circuit. This illustrates the use of+-- laziness in the Quipper circuit generation code.++-- Please note that currently only the ASCII backend can make actual+-- use of laziness; the graphics-based backends must generate the+-- whole circuit before it can be printed.++-- We also apply a transformer, to illustrate the laziness of+-- transformers as well.++circuit_with_error :: Qubit -> Qubit -> Qubit -> Circ (Qubit, Qubit, Qubit)+circuit_with_error q r s = do+ qnot_at q `controlled` [r,s]+ hadamard_at r+ error "A runtime error occurred!"+ hadamard_at r+ return (q, r, s) + +circuit_with_error_transformed = decompose_generic Binary circuit_with_error++main =+ print_simple ASCII circuit_with_error++main2 = + print_simple ASCII circuit_with_error_transformed
@@ -0,0 +1,41 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Example.hs" #-}++import Quipper+import Prelude hiding (and)++example1 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+example1 (a,b,c) = do+ qnot_at a `controlled` [b, c]+ hadamard b `controlled` [a]+ qnot_at a `controlled` [b, c]+ hadamard c `controlled` [a]+ return (a,b,c)++example2 :: Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example2 h a b c = do+ qnot_at c `controlled` [a, b]+ hadamard h `controlled` [c]+ qnot_at c `controlled` [a, b]++example3 :: Qubit -> Qubit -> Qubit -> Circ ()+example3 h a b = do+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard h `controlled` [c]+ qnot_at c `controlled` [a, b]++example4 :: (Qubit, Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit, Qubit)+example4 (a,b,c,d) = do+ qnot_at a+ qnot_at b+ with_controls (c .&&. d) $ do+ qnot_at a+ qnot_at b+ qnot_at c+ return (a,b,c,d)++main =+ print_simple Preview example4
@@ -0,0 +1,14 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Example1.hs" #-}+ import Quipper++ example1 (q, a, b, c) = do+ hadamard a+ qnot_at c `controlled` [a, b]+ hadamard q `controlled` [c]+ qnot_at c `controlled` [a, b]+ hadamard a++ main = print_simple Preview example1
@@ -0,0 +1,16 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Example2.hs" #-}+ import Quipper++ example2 (q, a, b) = do+ hadamard a+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard_at q `controlled` [c]+ qnot_at c `controlled` [a, b]+ hadamard_at a+ return (q, a, b)++ main = print_simple Preview example2
@@ -0,0 +1,25 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Example3.hs" #-}+import Quipper++example1 :: (Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit)+example1 (q, a, b, c) = do+ hadamard a+ qnot_at c `controlled` [a, b]+ hadamard q `controlled` [c]+ qnot_at c `controlled` [a, b]+ hadamard a+ return (q, a, b, c)++example3 :: (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit)+example3 (q, a, b, c, d, e) = do+ example1 (q, a, b, c)+ with_controls (d .==. 0 .&&. e .==. 1) $ do+ example1 (q, a, b, c)+ example1 (q, a, b, c)+ example1 (q, a, b, c)+ return (q, a, b, c, d, e)++main = print_simple Preview example3
@@ -0,0 +1,15 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Example4.hs" #-}+import Quipper++example4 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+example4(q, a, b) = do+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard q `controlled` [c]+ qnot_at c `controlled` [a, b]+ return (q, a, b)++main = print_simple Preview example4
@@ -0,0 +1,37 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/GPhase.hs" #-}+-- This file illustrates how global phase gates will be rendered in+-- graphical circuit diagrams.++import Quipper++mycirc :: (Qubit, Qubit, Qubit) -> Circ ()+mycirc (a,b,c) = do+ comment "Unanchored"+ global_phase 1.0+ + comment "Anchored at a"+ global_phase_anchored 1.0 a+ + comment "Anchored at b"+ global_phase_anchored 1.0 b+ + comment "Anchored at c"+ global_phase_anchored 1.0 c+ + comment "Anchored at (a,b)"+ global_phase_anchored 1.0 (a,b)+ +test :: (Qubit, Qubit, Qubit) -> Circ ()+test (a,b,c) = do + label (a,b,c) ("a", "b", "c")+ mycirc (a,b,c)+ mycirc (a,b,c) `controlled` a+ mycirc (a,b,c) `controlled` b+ mycirc (a,b,c) `controlled` c+ mycirc (a,b,c) `controlled` a .==. 1 .&&. b .==. 0 .&&. c .==. 0++main = + print_simple Preview test
@@ -0,0 +1,15 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/HelloWorld.hs" #-}+import Quipper++circuit :: Qubit -> Qubit -> Qubit -> Circ (Qubit, Qubit, Qubit, Qubit)+circuit a b c = do+ qnot_at a `controlled` c .==. 1+ hadamard_at b `controlled` c .==. 0+ d <- qinit False+ qnot_at d `controlled` b .==. 1+ return (a,b,c,d)++main = print_simple Preview circuit
@@ -0,0 +1,30 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Infinite.hs" #-}+import Quipper+import Quipper.Libraries.Decompose++-- Outputs an infinite circuit. This illustrates the use of laziness+-- in the Quipper circuit generation code. ++-- Please note that currently only the ASCII backend can make actual+-- use of laziness; the graphics-based backends must generate the+-- whole circuit before it can be printed.++-- We also apply a transformer, to illustrate the laziness of+-- transformers as well.++infinite_circuit :: Qubit -> Qubit -> Qubit -> Circ (Qubit, Qubit, Qubit)+infinite_circuit q r s = do+ qnot_at q `controlled` [r,s]+ hadamard_at r+ infinite_circuit s q r+ +infinite_circuit_transformed = decompose_generic Binary infinite_circuit++main1 = + print_simple ASCII infinite_circuit++main = + print_simple ASCII infinite_circuit_transformed
@@ -0,0 +1,34 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/MultiControlledNot.hs" #-}+-- | Demonstrates Quipper's decomposition of multiply-controlled+-- not-gates into the Clifford+/T/ gate set.++import Quipper+import Quipper.Libraries.Decompose++multi_cnot :: [Qubit] -> Qubit -> Circ ()+multi_cnot controls target = do+ qnot_at target `controlled` controls++multi_cnot_decomposed :: [Qubit] -> Qubit -> Circ ()+multi_cnot_decomposed = decompose_generic Exact multi_cnot++main_n :: Int -> IO ()+main_n n = do+ putStrLn ("Gate counts for " ++ show n ++ " controls:")+ putStrLn ""+ print_generic GateCount multi_cnot_decomposed (replicate n qubit) qubit+ putStrLn ""+ print_generic Preview multi_cnot_decomposed (replicate n qubit) qubit+ +main :: IO ()+main = do+ main_n 0+ main_n 1+ main_n 2+ main_n 3+ main_n 4+ main_n 5+ main_n 6
@@ -0,0 +1,26 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/NBox.hs" #-}+import Quipper+import Quipper.Libraries.Unboxing++rep :: Integer+rep = 3++myfunc :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+myfunc (a,b) = do+ hadamard_at a `controlled` b+ return (b,a)+ +circuit :: (Qubit, Qubit, Qubit, Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit, Qubit, Qubit, Qubit)+circuit (a,b,c,d,e,f) = do+ label (a,b,c,d,e,f) ("a","b","c","d","e","f")+ (a,b) <- loopM rep (a,b) myfunc+ (c,d) <- box_loopM "box1" rep (c,d) myfunc+ (e,f) <- unbox (\x -> box_loopM "box1" rep x myfunc) (e,f)+ label (a,b,c,d,e,f) ("a","b","c","d","e","f") + return (a,b,c,d,e,f)+ +main = + print_simple Preview circuit
@@ -0,0 +1,34 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/NamedGate.hs" #-}+import Quipper hiding (gate_V)++my_unary_gate :: Qubit -> Circ Qubit+my_unary_gate = named_gate "Q"++my_binary_gate :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+my_binary_gate = named_gate "R"++my_unary_gate_at :: Qubit -> Circ ()+my_unary_gate_at = named_gate_at "Q"++my_binary_gate_at :: (Qubit, Qubit) -> Circ ()+my_binary_gate_at = named_gate_at "R"++gate_V :: Qubit -> Circ Qubit+gate_V = named_gate "V"++circuit :: Qubit -> Qubit -> Circ (Qubit, Qubit)+circuit a b = do+ a <- gate_V a+ (c,d) <- my_binary_gate (a,b)+ c <- my_unary_gate a `controlled` d+ my_binary_gate_at (c, d)+ my_binary_gate_at (d, c)+ my_unary_gate_at d+ c <- gate_V c+ d <- gate_V d+ return (c,d)++main = print_simple Preview circuit
@@ -0,0 +1,78 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/NoControl.hs" #-}+import Quipper++-- | 'example1': do a basis change, then perform some operation, then+-- uncompute the basis change. Drawback: if this is later controlled,+-- then the controls are applied to the basis change too, which is+-- unnecessary.++example1 :: Qubit -> Qubit -> Circ ()+example1 a b = do+ -- basis change+ gate_W_at a b+ qnot_at b `controlled` a+ + -- some operation+ hadamard_at b `controlled` a+ + -- undo basis change+ qnot_at b `controlled` a+ gate_W_at a b ++-- | 'example2': low-level solution. The 'without_controls' operator+-- can be used to inhibit the addition of further controls to blocks+-- of code. (However, this is not very safe. A better way to do this+-- is shown in 'example3').++example2 :: Qubit -> Qubit -> Circ ()+example2 a b = do+ -- basis change+ without_controls $ do+ gate_W_at a b+ qnot_at b `controlled` a+ -- some operation+ hadamard_at b `controlled` a+ -- undo basis change+ without_controls $ do+ qnot_at b `controlled` a+ gate_W_at a b++-- | 'example3': a better way to achieve the effect of 'example2' is+-- to use the operator 'with_basis_change'. This will take care of the+-- uncomputation automatically, and also ensure that controls will not+-- be added to the basis change.+example3 :: Qubit -> Qubit -> Circ () +example3 a b = do+ with_basis_change basischange $ do+ hadamard_at b `controlled` a++ where+ basischange = do+ gate_W_at a b+ qnot_at b `controlled` a++-- | 'example4': a similar effect is introduced by the operator+-- 'with_ancilla'. Normally, the gates that initialize and terminate+-- ancillas cannot be controlled. However, when using the+-- 'with_ancilla' operator, the resulting circuit can be controlled as+-- a whole, provided that the body is controllable.++example4 :: Qubit -> Qubit -> Circ ()+example4 a b = do+ with_ancilla $ \d -> do+ with_basis_change (qnot_at d `controlled` b .==. False) $ do+ hadamard_at a `controlled` d++my_circuit :: Qubit -> Qubit -> Qubit -> Circ ()+my_circuit ctrl a b = do+ example1 a b `controlled` ctrl+ example2 a b `controlled` ctrl+ example3 a b `controlled` ctrl+ example4 a b `controlled` ctrl++main =+ print_simple Preview my_circuit+
@@ -0,0 +1,86 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/OptimTest.hs" #-}+-- | A test for the 'simplify_classical' function. As an example, we use+-- a simple adder defined using the @build_circuit@ keyword. 'main1'+-- outputs the unoptimized circuit, and 'main2' outputs the optimized+-- version.++import Quipper+import Quipper.Libraries.ClassicalOptim+import Quipper.Utils.Auxiliary++-- | Return the majority of three booleans.++majority :: Bool -> Bool -> Bool -> Bool+majority a b c = if (a `bool_xor` b) then c else a+++{-# LINE 14 "Quipper/Demos/OptimTest.hs" #-}+$( decToCircMonad [d| majority :: Bool -> Bool -> Bool -> Bool+ majority a b c = if (a `bool_xor` b) then c else a+ + + |] ) +{-# LINE 15 "Quipper/Demos/OptimTest.hs" #-}+-- | Bit adder. The first input is 'False' for adding, and 'True' for+-- subtracting. The second input is a triple consisting of a carry,+-- and two bits to be added. The output consists of the new carry and+-- the sum.++bit_adder :: Bool -> (Bool,Bool,Bool) -> (Bool,Bool)+bit_adder sign (carry, x,y) =+ let y' = y `bool_xor` sign in+ let z = carry `bool_xor` x `bool_xor` y' in+ let carry' = majority carry x y' in+ (carry', z)+++{-# LINE 26 "Quipper/Demos/OptimTest.hs" #-}+$( decToCircMonad [d| bit_adder :: Bool -> (Bool,Bool,Bool) -> (Bool,Bool)+ bit_adder sign (carry, x,y) =+ let y' = y `bool_xor` sign in+ let z = carry `bool_xor` x `bool_xor` y' in+ let carry' = majority carry x y' in+ (carry', z)+ + + |] ) +{-# LINE 27 "Quipper/Demos/OptimTest.hs" #-}+-- | Multi-bit adder. Add two /n/-bit integers, represented as+-- little-tailian bit lists.++adder :: [Bool] -> [Bool] -> [Bool]+adder f l = + reverse $ snd $ fold_right_zip (bit_adder False) (False, reverse l, reverse f)+++{-# LINE 33 "Quipper/Demos/OptimTest.hs" #-}+$( decToCircMonad [d| adder :: [Bool] -> [Bool] -> [Bool]+ adder f l = + reverse $ snd $ fold_right_zip (bit_adder False) (False, reverse l, reverse f)+ + + |] ) +{-# LINE 34 "Quipper/Demos/OptimTest.hs" #-}+-- | Wrapper around 'template_adder'.+myAdder :: ([Qubit],[Qubit]) -> Circ [Qubit]+myAdder (x,y) = do+ label (x,y) ("x","y")+ z <- unpack template_adder x y+ label z "z"+ return (z)++main1 :: IO()+main1 = do+ print_generic Preview myAdder (replicate 3 qubit, replicate 3 qubit)++main2 :: IO()+main2 = do+ print_generic Preview (simplify_classical myAdder) (replicate 3 qubit, replicate 3 qubit)++main :: IO()+main = main2++
@@ -0,0 +1,43 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/ParseNodeRoot.hs" #-}+import Quipper++import Quipper.Libraries.Qureg++-- | Algorithm 7. The arguments are of the form (/a/, /root/, /even/,+-- /n/). Precondition: /a/ is a quantum register of length at least+-- /n/+1.+parseNodeRoot :: (Qureg, Qubit, Qubit, Int) -> Circ ()+parseNodeRoot (a, root, even, n) = do+ comment_with_label "ENTER: parseNodeRoot" (a, root, even) ("a", "root", "even")+ with_ancilla_reg (n+1) $ \scratch -> do+ for n 1 (-1) $ \index -> do + with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ endfor+ with_controls (scratch.!(0) .==. 0) $ do {+ qnot_at root;+ qnot_at even+ }+ for 1 n 1 $ \index -> do + with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1))+ }+ endfor+ comment_with_label "EXIT: parseNodeRoot" (a, root, even) ("a", "root", "even")+ return ()+ +main = print_generic Preview circuit (qureg_shape (n+1), qubit, qubit) + where+ circuit (a, root, even) = parseNodeRoot (a, root, even, n)+ n = 4+
@@ -0,0 +1,26 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/PhaseTest.hs" #-}+-- $ Test whether the quantum simulator works correctly on a global+-- phase gate.++import Quipper+import Quipper.Libraries.Simulation++-- | This function should compute a Not gate.+testcirc :: Qubit -> Circ Qubit+testcirc a = do+ hadamard_at a+ global_phase 1.0 `controlled` a+ hadamard_at a+ return a+ +main = do+ b <- run_generic_io d testcirc False+ putStrLn ("testcirc False = " ++ show b)+ b <- run_generic_io d testcirc True+ putStrLn ("testcirc True = " ++ show b)+ where+ d :: Double+ d = undefined
@@ -0,0 +1,143 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/QEC.hs" #-}++import Quipper++-- import other stuff+import Control.Monad (zipWithM_)++-- ======================================================================+-- ALGORITHM SPECIFIC CODE++{- the test circuit from Alex V. and Benoit's email. It looks like+this:++In Alex's notation: ++ H(a)+ c = meas(a)+ if c then+ X(b)+ else Y(b)++In circuit notation:++ a -H--Meas===x==o==|+ | |+ b -----------X--Y----++In QPL notation: +-} ++testcircuit :: (Qubit, Qubit) -> Circ Qubit+testcircuit (a,b) = do+ hadamard a+ c <- measure a+ with_controls (c .==. 1) $ do {+ gate_X_at b+ }+ with_controls (c .==. 0) $ do {+ gate_Y_at b+ }+ cdiscard c+ return b++-- Let's see if we can implement some parts of the Steane+-- code. Working from Alex V.'s notes.+++-- prepare the logical |+〉 state for the Steane code. This returns a list+-- of 7 qubits+plusState :: Circ [Qubit]+plusState = do+ -- prepare (a...g) in the state "00+0+++"+ [a,b,c,d,e,f,g] <- qinit_of_string "00+0+++"++ qnot_at a `controlled` c .==. 1+ qnot_at d `controlled` f .==. 1+ qnot_at b `controlled` g .==. 1+ qnot_at a `controlled` e .==. 1+ qnot_at d `controlled` g .==. 1+ qnot_at b `controlled` f .==. 1+ qnot_at a `controlled` g .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at d `controlled` e .==. 1+ + return [a,b,c,d,e,f,g]++-- prepare the logical |0〉 state for the Steane code+zeroState :: Circ [Qubit]+zeroState = do+ -- prepare (a...g) in the state "00+0+++"+ [a,b,c,d,e,f,g] <- qinit_of_string "++0+000"++ qnot_at c `controlled` a .==. 1+ qnot_at f `controlled` d .==. 1+ qnot_at g `controlled` b .==. 1+ qnot_at e `controlled` a .==. 1+ qnot_at g `controlled` d .==. 1+ qnot_at f `controlled` b .==. 1+ qnot_at g `controlled` a .==. 1+ qnot_at c `controlled` b .==. 1+ qnot_at e `controlled` d .==. 1+ + return [a,b,c,d,e,f,g]++preparePlus :: Circ ([Qubit], Bit)+preparePlus = do+ qs <- plusState+ vs <- plusState+ zipWithM_ (\q v -> qnot_at q `controlled` v .==. 1) qs vs+ measure <- mapM measure vs+ result <- cgate_and measure+ mapM_ cdiscard measure+ return (qs, result)++{-+-- this function operates on a 7-tuple of qubits, which are inputs and+-- outputs. The additional output Bit is 0 when the error correction+-- fails, else 1+preGateCorrection :: (Qubit,Qubit,Qubit,Qubit,Qubit,Qubit,Qubit) -> Bit+preGateCorrection q = do+ result = cinit_bit False+ (a, av, result_a) <- preparePlus []+ with_controls (result_a .==. 1) $ do {+ (b, bv, result_b) <- prepareZero+ with_controls (result_b .==. 1) $ do {+ zRecover(q, a),+ xRecover(q, b),+ cnot result+ }+ with_controls (result_b .==. 0) $ do {+ .....+-}++ +-- ======================================================================+-- main functions (ugly, don't follow an "idiom" yet)++-- this is just a main function to print the circuit+main_testcircuit :: IO()+main_testcircuit =+ print_generic Preview testcircuit (qubit,qubit)++-- this is just a main function to print the circuit+main_plusState :: IO()+main_plusState =+ print_generic Preview plusState++-- this is just a main function to print the circuit+main_zeroState :: IO()+main_zeroState =+ print_generic Preview zeroState+ +-- this is just a main function to print the circuit+main_preparePlus :: IO()+main_preparePlus =+ print_generic Preview preparePlus+ +main = main_preparePlus++
@@ -0,0 +1,9 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/QFT.hs" #-}+import Quipper+import Quipper.Libraries.QFT++main :: IO ()+main = print_generic Preview qft_little_endian (replicate 5 qubit)
@@ -0,0 +1,68 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/QFTAdder.hs" #-}+import Quipper+import Quipper.Libraries.Arith+import Quipper.Libraries.QFTAdd+import Quipper.Libraries.Simulation+import Quipper.Libraries.Unboxing++import System.Environment++------ Functions for testing the QFTAdd circuit --------++-- | Output a preview of the qft_add_in_place circuit for quantum integers of+-- the given size+print_qft_add :: Int -> IO ()+print_qft_add m = print_generic Preview qft_add_in_place (qdint_shape m) (qdint_shape m)++-- | Simulate the running of the qft_add_in_place circuit for the given IntM inputs+run_qft_add :: IntM -> IntM -> IO (IntM,IntM)+run_qft_add = run_generic_io (undefined :: Double) (unbox qft_add_in_place)++-- | A wrapper around 'run_qft_add' so that it can be used with standard Integer+-- arguments.+test_add :: Integer -> Integer -> IO Integer+test_add a b = if (a < 0) || (b < 0) then error "test_add: negative argument" else+ do+ let m = 2 + ceiling (log (fromInteger (a+b)) / log 2) -- a slight cheat to work out how many qubits to use+ let a' = intm m a+ let b' = intm m b+ (_,ab) <- run_qft_add a' b'+ return (fromIntegral ab)++-- | A datatype for the possible command line arguments+data Args = Usage | One Int | Two Integer Integer ++-- | A function to parse the command line arguments+parseArgs :: [String] -> Args+parseArgs [s1] = case reads s1 of+ [(x1,_)] -> One x1+ _ -> Usage+parseArgs [s1,s2] = case (reads s1,reads s2) of+ ([(x1,_)],[(x2,_)]) -> Two x1 x2+ _ -> Usage+parseArgs _ = Usage++-- | The main function calls either test_add or print_qft_add depending upon+-- command line arguments.+main :: IO ()+main = do+ args <- getArgs+ case parseArgs args of+ Usage -> usage+ One x -> print_qft_add x+ Two x1 x2 -> do+ res <- test_add x1 x2+ putStrLn (show x1 ++ " + " ++ show x2 ++ " = " ++ show res)++usage :: IO ()+usage = do+ name <- getProgName+ putStrLn ("usage: " ++ name ++ " num1 <num2>") + putStrLn " - one argument:"+ putStrLn " preview the circuit for quantum integers of that length"+ putStrLn " - two arguments:"+ putStrLn " simulate the circuit for adding the two numbers"+ putStrLn " (note that quantum simulation is not efficient)"
@@ -0,0 +1,19 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/QRAM.hs" #-}++import Quipper+import Quipper.Libraries.Qram+import Quipper.Libraries.Arith++test_qram :: [Qubit] -> QDInt -> Circ ()+test_qram list index = do+ label (list,index) ("list","index")+ with_computed (indexed_access list index) $ \element -> do+ label element "element"+ hadamard_at element+++main :: IO ()+main = print_generic Preview test_qram (replicate 8 qubit) (qdint_shape 3)
@@ -0,0 +1,129 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/QuantumIfTest.hs" #-}+import Quipper+import Quipper.Libraries.Simulation+import Quipper.Libraries.QuantumIf++-- ----------------------------------------------------------------------+-- * Testing quantum \"if then else\"++-- | A dummy value of type Double, to feed the type in the simulator+double :: Double+double = undefined++-- | A testing function that displays a circuit that tests the 'if_then_elseQ'+-- statement, and the results of running the circuit on various inputs.+if_test :: IO ()+if_test = do+ print_simple ASCII ifTest2+ print_simple Preview ifTest2+ res0 <- run_generic_io double ifTest2 (False,False,False)+ putStrLn (show res0)+ res1 <- run_generic_io double ifTest2 (False,False,True)+ putStrLn (show res1)+ res2 <- run_generic_io double ifTest2 (False,True,False)+ putStrLn (show res2)+ res3 <- run_generic_io double ifTest2 (False,True,True)+ putStrLn (show res3)+ res4 <- run_generic_io double ifTest2 (True,False,False)+ putStrLn (show res4)+ res5 <- run_generic_io double ifTest2 (True,False,True)+ putStrLn (show res5)+ res6 <- run_generic_io double ifTest2 (True,True,False)+ putStrLn (show res6)+ res7 <- run_generic_io double ifTest2 (True,True,True) + putStrLn (show res7)++-- | A test of the 'if_then_elseQ' function.+ifTest :: Circ (Qubit,Qubit,Qubit)+ifTest = do+ (q0,q1,q2,q3,q4,q5,q6) <- qinit (False,False,False,False,False,False,False)+ qnot_at q4+ if_then_elseQ (Or (A q0) (And (A q1) (Not (A q2))))+ ( --if q0 | (q1 & !q2)+ qnot_at q4+ )+ (+ if_then_elseQ (And (A q2) (A q3))+ ( --else if+ qnot_at q5 + )+ ( -- else+ qnot_at q6+ )+ )+ return (q4,q5,q6) ++-- | Another test of the 'if_then_elseQ' function.+ifTest2 :: (Qubit,Qubit,Qubit) -> Circ (Qubit,Qubit)+ifTest2 (l,p,d) = do+ ctrl <- qinit True+ (x,y) <- qinit (False,False)+ with_controls ctrl + (+ do + if_then_elseQ (Or (A l) (And (A p) (Not (A d))))+ ( --if l | (p & !d) + qnot_at x+ )+ ( -- else+ qnot_at y+ )+ )+ qdiscard (l,p,d)+ qterm True ctrl+ return (x,y)++-- | A simple test of the 'if_then_elseQ' function.+ifTest3 :: Qubit -> Circ (Qubit,Qubit)+ifTest3 q = do+ (q0,q1) <- qinit (False,False)+ if_then_elseQ (A q)+ (+ qnot_at q0+ )+ (+ qnot_at q1+ )+ qdiscard q+ return (q0,q1) ++-- | A small circuit for testing 'if_then_elseQinv' statements.+small_circ :: [Qubit] -> Circ ([Qubit],Qubit,Qubit)+small_circ qs = do+ (q1,q2) <- qinit (False,False)+ tempReg0 <- qinit (replicate (length qs) False)+ tempReg1 <- qinit (replicate (length qs) True)+ let boolean_statement = foldr1 (\x y -> And x y) (map A qs)+ let boolean_statement_out = Not boolean_statement+ if_then_elseQinv boolean_statement+ (+ do+ qnot_at q1+ swap (reverse tempReg0) (reverse qs)+ return ()+ )+ (+ do+ swap tempReg1 qs+ qnot_at q2+ ) boolean_statement_out+ return (qs,q1,q2) ++-- | Display the 'small_circ'.+print_small_circ :: IO ()+print_small_circ = print_generic Preview small_circ (replicate 4 qubit) ++-- | Simulate the 'small_circ'.+test_small_circ :: [Bool] -> IO ()+test_small_circ bs = do+ putStr (show bs ++ " -> ")+ res <- run_generic_io double small_circ bs+ putStrLn (show res)++-- | A main function.+main :: IO ()+main = test_small_circ [True,True,False]+
@@ -0,0 +1,17 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Reverse.hs" #-}+import Quipper++my_circuit :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+my_circuit (a,b) = do+ qnot_at a `controlled` b+ hadamard b `controlled` a+ return (a,b) + +rev_circuit :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+rev_circuit = reverse_simple my_circuit++main =+ print_simple Preview rev_circuit
@@ -0,0 +1,759 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Algorithms/BWT/Alternative.hs" #-}+{-# LANGUAGE FlexibleContexts #-}++-- | Alternative implementations for the binary welded tree algorithm.+-- The purpose of these is to experiment with and potentially+-- illustrate a more functional programming style.++module Quipper.Algorithms.BWT.Alternative where++import Quipper++import Quipper.Libraries.Qureg+import Quipper.Libraries.Simulation++import Quipper.Algorithms.BWT.Definitions++-- import other Quipper stuff+import qualified Quipper.Algorithms.BWT.BWT as BWT++import Quipper.Utils.Sampling+import Quipper.Utils.Auxiliary++-- import other stuff+import Control.Monad+import Text.Printf+import Data.Bits (xor)+import Text.Printf++import Data.Map (Map)+import qualified Data.Map as Map+++-- ======================================================================+-- * Oracle abstraction++-- | This is a version of 'BWT.Oracle' that uses 'Qulist' instead of+-- 'Qureg'. An oracle provides the following information: the tree+-- depth /n/, the label length /m/, the number of edge colors /k/,+-- the entrance label /ENTRANCE/, and for each color 0 ≤ /c/ < /k/,+-- a reversible circuit /ORACLE[sub c](a,b,r)/.++data Oracle = Oracle {+ n :: Int,+ m :: Int,+ k :: Int,+ entrance :: Boollist,+ oraclefun :: Int -> (Qulist, Qulist, Qubit) -> Circ ()+}++-- | Convert a "Alternative".'Oracle' into a "BWT".'BWT.Oracle'.+convert_oracle :: Oracle -> BWT.Oracle+convert_oracle Oracle { n=n, m=m, k=k, entrance=e, oraclefun=f1 } =+ BWT.Oracle { BWT.n=n, BWT.m=m, BWT.k=k, BWT.entrance=e, BWT.oraclefun=f2 } + where + f2 c (a, b, r) = f1 c (qulist_of_qureg_te a, qulist_of_qureg_te b, r)++-- ======================================================================+-- * Top-level algorithm++-- | Do a quantum random walk on the binary welded tree given by the+-- oracle, for /s/ times steps of length /dt/. Return a bit list+-- corresponding to the probable exit label. This is a more+-- functional implementation of 'BWT.qrwbwt' from the module "BWT".+-- +-- Note: This implementation does not rely on the oracle being+-- self-inverse, and therefore only requires that+-- +-- > ORACLE[sub c](a, 0, 0) = (a, v[sub c](a), f[sub c](a)), +-- +-- rather than the more general property +-- +-- > ORACLE[sub c](a, b, r) = (a, b ⊕ v[sub c](a), r ⊕ f[sub c](a)). +-- +-- This gives us the freedom to build more efficient oracles, where+-- appropriate.+qrwbwt :: Oracle -> Timestep -> Int -> Circ Bitlist+qrwbwt oracle dt s = do+ comment (printf "ENTER: qrwbwt (dt=%.3e, s=%d)" dt s)+ -- Initialize a to the entrance label.+ a <- qinit (entrance oracle)++ -- Run the Hamiltonian /s/ times for time step /dt/.+ replicateM s $ hamiltonian dt oracle a++ -- Measure /a/.+ exit <- measure a+ comment_with_label "EXIT: qrwbwt" exit "exit"+ return exit++-- | Apply one round of the Hamiltonian for time step /dt/ to /a/.+hamiltonian :: Timestep -> Oracle -> Qulist -> Circ ()+hamiltonian dt oracle a = do+ comment_with_label "ENTER: hamiltonian" a "a"+ for 0 ((k oracle)-1) 1 $ \c -> do+ -- for c from 0 to k-1++ -- create ancillas b and r+ with_ancilla_list (length a) $ \b -> do+ with_ancilla $ \r -> do++ -- perform computations+ (oraclefun oracle) c (a,b,r)+ time_step dt (a,b,r)+ reverse_generic_imp ((oraclefun oracle) c) (a,b,r)+ -- "reverse" here is not quite GFI+ comment_with_label "EXIT: hamiltonian" a "a"++-- | Apply the diffusion step to /(a,b,r)/. Here /a/ and /b/ must be+-- of equal length.+time_step :: Timestep -> (Qulist, Qulist, Qubit) -> Circ ()+time_step dt (a,b,r) = do+ comment_with_label "ENTER: time_step" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ basischange (a,b,h)+ controlledExpGate (dt,r,h)+ (reverse_generic_imp basischange) (a,b,h)+ comment_with_label "EXIT: time_step" (a,b,r) ("a","b","r")++-- | Apply the basis change from Figure 3 of \[Childs et al.\] to /a/,+-- /b/, and /h/. Here /a/ and /b/ must be of equal length.+basischange :: (Qulist, Qulist, Qubit) -> Circ ()+basischange (a,b,h) = do+ comment_with_label "ENTER: basischange" (a,b,h) ("a","b","h")+ -- apply W gates+ zipWithM_ gate_W a b+ -- apply doubly-controlled not-gates+ zipWithM_ (dc_not h) a b+ comment_with_label "EXIT: basischange" (a,b,h) ("a","b","h")+ where+ dc_not h x y = qnot_at h `controlled` (x .==. 1 .&&. y .==. 0)+ +-- | Compute the required number of iterations as a function of ε and+-- /dt/.+-- +-- Inputs: /n/ is the tree depth, ε is the desired precision, /dt/ is+-- the simulation time step. Intermediate values: /t/ is the+-- simulation time. Output: /s/, the upper bound on the number of+-- simulation time steps.+-- +-- Note: \[Childs et al\] specifies that /t/ should be chosen+-- uniformly at random within the interval 0 < /t/ ≤ /n/[sup 4]\/2ε.+-- Here, for simplicity, we just use /t/ = ⌊/n/[sup 4]\/2ε⌋. Also note+-- that this function is for information only, as it is not actually+-- used. Users should specify /s/ directly.+compute_steps :: Int -> Double -> Double -> Int+compute_steps n epsilon dt =+ floor (t / dt)+ where+ t = fromIntegral (n * n * n * n) / (2.0 * epsilon)++-- ======================================================================+-- * Oracle implementations++-- ** Blackbox oracle++-- | A blackbox oracle for testing. This just produces a labelled box+-- in place of the actual oracle circuit. The argument is the tree+-- height.+oracle_blackbox :: Int -> Oracle+oracle_blackbox n = + let m = n+2 in+ Oracle {+ n = n,+ m = m,+ k = 4,+ entrance = boollist_of_int_bh (n+2) 1,+ oraclefun = \c (a, b, r) ->+ do+ named_gate_at ("O(" ++ show c ++ ")") (a ++ b ++ [r])+ return ()+ }++-- ----------------------------------------------------------------------+-- ** A simple \"exponential\" oracle.++-- | This oracle, which works only for the fixed tree height 3, works+-- by explicitly listing all the edges. It serves only to illustrate+-- how the edge information is encoded. Listing all edges explicitly+-- obviously would not scale well to larger graphs.+oracle_simple :: Oracle+oracle_simple =+ let n = 3+ m = 5+ k = 4++ invalid = 0 -- also works correctly for invalid = 31+ invalid_vec = boollist_of_int_bh m invalid++ green = 0+ blue = 1+ red = 2+ black = 3++ edges :: Int -> [(Int, Int)]+ edges 0 = [(1,3), (2,5), (4,8), (6,12), (7,15), (9,17), (10,18),+ (13,21), (19,25), (22,27), (24,28), (26,29)]+ edges 1 = [(2,4), (3,6), (5,10), (7,14), (8,16), (11,19), (12,20),+ (17,24), (21,26), (23,27), (25,28), (29,30)]+ edges 2 = [(1,2), (3,7), (4,9), (5,11), (6,13), (14,22), (15,23),+ (16,24), (18,25), (20,26), (27,29), (28,30)]+ edges 3 = [(8,17), (9,18), (10,19), (11,20), (12,21), (13,22),+ (14,23), (15,16)]+ edges n = error ("oracle_simple: illegal color: " ++ show n)++ -- apply an (a,n1)-controlled not operation to (v,n2)+ multi_controlled_multi_not :: Int -> (Qulist, Qulist) -> (Int, Int) -> Circ ()+ multi_controlled_multi_not m (a,v) (n1, n2) = do+ let vec1 = boollist_of_int_bh m n1+ let vec2 = boollist_of_int_bh m n2+ bool_controlled_not v vec2 `controlled` a .==. vec1+ return ()++ -- the O_c circuit+ oracle_O :: Int -> (Qulist, Qulist) -> Circ ()+ oracle_O c (a,v) = do+ let e = edges c+ foreach e $ \(n1, n2) -> do+ multi_controlled_multi_not m (a,v) (n1, invalid `xor` n2)+ multi_controlled_multi_not m (a,v) (n2, invalid `xor` n1)++ -- the B_c circuit+ oracle_B :: (Qulist, Qulist) -> Circ ()+ oracle_B (v,b) =+ for 0 (m-1) 1 $ \i -> do+ qnot_at (b !! i) `controlled` (v !! i) .==. 1++ -- the R_c circuit+ oracle_R :: (Qulist, Qubit) -> Circ ()+ oracle_R (v,r) = do+ qnot_at r `controlled` v .==. invalid_vec++ -- the oracle circuit+ oraclefun :: Int -> (Qulist, Qulist, Qubit) -> Circ ()+ oraclefun c (a,b,r) = do+ comment_with_label "ENTER: oracle_simple" (a,b,r) ("a","b","r")+ with_ancilla_init invalid_vec $ \v -> do+ oracle_O c (a,v)+ oracle_B (v,b)+ oracle_R (v,r)+ oracle_O c (a,v)+ comment_with_label "EXIT: oracle_simple" (a,b,r) ("a","b","r")++ in++ -- return the oracle object+ Oracle { n = n,+ m = m,+ k = k,+ entrance = boollist_of_int_bh m 1,+ oraclefun = oraclefun+ }++-- ======================================================================+-- ** Alternate implementations of the \"orthodox\" oracle++-- ----------------------------------------------------------------------+-- *** Classical implementation++-- $ In this section, we first implement the oracle function +-- /v[sub c](a)/ as a classical boolean function. This implementation+-- is just for reference, and attempts to be neither efficient nor+-- quantum. It can, however, be used as a specification to test the +-- actual quantum oracles against. +-- +-- Both the classical circuit implementation (below) and the Template+-- Haskell implementation (in the module "BWT.Template") were derived+-- from this.+-- +-- We start with several auxiliary functions.++-- | The type of nodes: a pair of a tree bit and a node address.+type Node = (Bool, [Bool])++-- | Convert integers to nodes, mainly for testing.+node_of_int :: Int -> Int -> Node+node_of_int m a = node_of_boollist (boollist_of_int_bh m a)++-- | Convert nodes to integers, mainly for testing.+int_of_node :: Node -> Int+int_of_node n = int_of_boollist_unsigned_bh (boollist_of_node n)++-- | Convert a bit vector to a node.+node_of_boollist :: [Bool] -> Node+node_of_boollist (t:a) = (t,a)+node_of_boollist [] = error "node_of_boollist: empty boollist"++-- | Convert a node to a bit vector.+boollist_of_node :: Node -> [Bool]+boollist_of_node (t,a) = t:a++-- | Input a node /a/ and return the parent of /a/. We assume that /a/+-- is not a root or invalid.+parent :: Node -> Node+parent (t, aa) = (t, False : init aa)++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True',+-- respectively). Assumes that /a/ is not a leaf.+childintree :: Node -> Bool -> Node+childintree (t, h:aa) childbit = (t, aa ++ [childbit])+childintree _ _ = error "childintree: invalid node"++-- | @'bit_adder' 'False'@ is a one-bit adder, and @'bit_adder' 'True'@ is+-- a one-bit subtracter (i.e., add the 2's complement of /y/).+bit_adder :: Bool -> (Bool, Bool, Bool) -> (Bool, Bool)+bit_adder sign (carry, x, y) = (carry', z)+ where+ y' = y `bool_xor` sign+ z = carry `bool_xor` x `bool_xor` y'+ carry' = majority carry x y'+ majority a b c = if a==b then a else c++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit; /a/+-- is the highest bit and /aa/ is the remaining /n/ bits) and a sign+-- /s/ (where 'True' = negative, 'False' = positive). Return+-- /a/:(/aa/ + /s/ * /f/). The first input is the /n/-bit welding+-- vector /f/ (a parameter to the oracle). Note that /f/ is a+-- parameter and /s/, /aa/ are inputs.+doweld1 :: Boollist -> Bool -> [Bool] -> [Bool]+doweld1 f s (a:aa) = a : aa' where+ aa' = snd $ fold_right_zip (bit_adder s) (s, aa, f)+doweld1 f s [] = error "doweld1: invalid node"++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit), and+-- return /a/:(/aa/ ⊕ /g/). The first input is the /n/-bit welding+-- vector /g/ (a parameter to the oracle).+doweld0 :: Boollist -> [Bool] -> [Bool]+doweld0 g (a:aa) = a : aa' where+ aa' = g `boollist_xor` aa+doweld0 g [] = error "doweld0: invalid node"++-- | Input a leaf node /a/ and return the left or right weld of /a/ in+-- the other tree (depending on whether the /weldbit/ is 'False' or+-- 'True'). Assumes that /a/ is a leaf.+weld :: Boollist -> Boollist -> Node -> Bool -> Node+weld f g (t, aa) weldbit = (not t, bb)+ where+ bb = if weldbit+ then doweld1 g t aa+ else doweld0 f aa++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True'. This+-- works for leaf and non-leaf nodes.+child :: Boollist -> Boollist -> Node -> Bool -> Node+child f g (t, aa) childbit =+ case aa of+ True : _ -> -- This is a leaf+ weld f g (t, aa) childbit+ False : _ -> -- This is not a leaf+ childintree (t, aa) childbit+ _ -> error "child: invalid node"++-- | Input a node address (without the tree bit) and return the parity+-- of the node level expressed as a boolean either 'False' or+-- 'True'. Leaves have parity 'False', and other levels have+-- alternating parities. In other words: count the number of leading+-- zeros modulo 2.+level_parity :: [Bool] -> Bool+level_parity [] = False+level_parity (h:t) = if h then False else not (level_parity t)++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node address is invalid. In other words, return 'True' iff the+-- list consists of all 0's.+is_zero :: [Bool] -> Bool+is_zero [] = True+is_zero (h:t) = if h then False else is_zero t++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node is a root or invalid. In other words, check whether all+-- digits but the last are 0's.+is_root :: [Bool] -> Bool+is_root [] = True+is_root (h:[]) = True+is_root (h:t) = if h then False else is_root t++-- | @'v_function' f g c a@: returns /v/[sub /c/](/a/), the label of the+-- node connected to /a/ by an edge of color /c/, or 'Nothing' if+-- there is no such node. The parameters /f/ and /g/ encode the+-- welding functions, and are lists of length /n/. /c/ is a color in+-- the range 0..3, and /a/ is an (/n/+2)-bit node label.+v_function :: Boollist -> Boollist -> Int -> Node -> Maybe Node+v_function f g c a =+ let (t,aa) = a+ bc_hi = level_parity aa+ z = is_zero aa+ e = is_root aa+ a1 = if last aa then True else False+ [c_hi, c_lo] = boollist_of_int_bh 2 c+ [cbc_hi, cbc_lo] = [c_hi `bool_xor` bc_hi, c_lo]+ in+ if not e && [cbc_hi, cbc_lo] == [True, a1] then Just(parent a) else+ if not z && cbc_hi == False then Just(child f g a cbc_lo) else+ Nothing++-- ----------------------------------------------------------------------+-- *** Auxiliary functions++-- | The type of nodes: a pair of a tree bit and a node address.+type CNode = (Bit, Bitlist)++-- | Like 'CNode', but uses qubits instead of classical bits.+type QNode = (Qubit, [Qubit])++-- | Convert a 'Qulist' to a 'QNode'.+qnode_of_qulist :: Qulist -> QNode+qnode_of_qulist (t:a) = (t,a)+qnode_of_qulist [] = error "qnode_of_qulist: empty list"++-- | Convert a 'Bitlist' to a 'CNode'.+cnode_of_bitlist :: Bitlist -> CNode+cnode_of_bitlist (t:a) = (t,a)+cnode_of_bitlist [] = error "cnode_of_bitlist: empty list"++-- | Exclusive or operation on bit vectors.+cboollist_xor :: Bitlist -> Bitlist -> Circ Bitlist+cboollist_xor = zipWithM (\x y -> cgate_xor [x,y])++-- ----------------------------------------------------------------------+-- *** Classical circuit implementation++-- $ We now implement the oracle function v[sub c](a) as a classical+-- circuit, with /c/ as a parameter. We don't try to be clever or+-- efficient yet. The implementation follows the \"classical+-- implementation\" above, but must be reformulated due to the need to+-- work within the 'Circ' monad.++-- | Input a node /a/ and return the parent of /a/. We assume that /a/+-- is not a root or invalid.+cparent :: CNode -> Circ CNode+cparent (t, aa_in) = do+ comment_with_label "ENTER: cparent" (t, aa_in) ("t", "aa_in")+ false <- cinit False+ let aa_out = false : init aa_in+ comment_with_label "EXIT: cparent" (t, aa_out) ("t", "aa_out")+ return (t, aa_out)++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True',+-- respectively). Assumes that /a/ is not a leaf.+cchildintree :: CNode -> Bit -> Circ CNode+cchildintree (t, node_in@(h:aa)) childbit = do+ comment_with_label "ENTER: cchildintree" (t, node_in) ("t", "node_in")+ let node_out = aa ++ [childbit]+ comment_with_label "EXIT: cchildintree" (t, node_out) ("t", "node_out")+ return (t, node_out)+cchildintree _ _ = error "cchildintree: invalid node"++-- | @'bit_adder' 'False'@ is a one-bit adder, and @'bit_adder' 'True'@ is+-- a one-bit subtracter (i.e., add the 2's complement of /y/).+cbit_adder :: Bit -> (Bit, Bit, Bit) -> Circ (Bit, Bit)+cbit_adder sign (carry_in, x, y) = do+ comment_with_label "ENTER: cbit_adder" (sign, carry_in, x, y) ("sign", "carry_in", "x", "y")+ y' <- cgate_xor [y, sign]+ z <- cgate_xor [carry_in, x, y']+ carry_out <- cmajority carry_in x y'+ comment_with_label "EXIT: cbit_adder" (carry_out, z) ("carry_out", "z")+ return (carry_out, z)+ where+ cmajority a b c = do+ cond <- cgate_eq a b+ cgate_if cond a c++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit; /a/+-- is the highest bit and /aa/ is the remaining /n/ bits) and a sign+-- /s/ (where 'True' = negative, 'False' = positive). Return+-- /a/:(/aa/ + /s/ * /f/). The first input is the /n/-bit welding+-- vector /f/ (a parameter to the oracle). Note that /f/ is a+-- parameter and /s/, /aa/ are inputs.+cdoweld1 :: Boollist -> Bit -> Bitlist -> Circ Bitlist+cdoweld1 f s node_in@(a:aa) = do+ comment_with_label "ENTER: cdoweld1" (s, node_in) ("s", "node_in")+ f' <- cinit f+ (_,aa') <- fold_right_zipM (cbit_adder s) (s, aa, f')+ let node_out = a : aa'+ comment_with_label "EXIT: cdoweld1" node_out "node_out"+ return node_out+cdoweld1 f s [] = error "cdoweld1: invalid node"++-- | Input an /n/+1-bit leaf node /a/:/aa/ (without the tree bit), and+-- return /a/:(/aa/ ⊕ /g/). The first input is the /n/-bit welding+-- vector /g/ (a parameter to the oracle).+cdoweld0 :: Boollist -> Bitlist -> Circ Bitlist+cdoweld0 g node_in@(a:aa) = do+ comment_with_label "ENTER: cdoweld0" node_in "node_in"+ g' <- cinit g+ aa' <- g' `cboollist_xor` aa+ let node_out = a:aa'+ comment_with_label "EXIT: cdoweld0" node_out "node_out"+ return node_out+cdoweld0 g [] = error "cdoweld0: invalid node"++-- | Input a leaf node /a/ and return the left or right weld of /a/ in+-- the other tree (depending on whether the /weldbit/ is 'False' or+-- 'True'). Assumes that /a/ is a leaf.+cweld :: Boollist -> Boollist -> CNode -> Bit -> Circ CNode+cweld f g node_in@(t, aa) weldbit = do+ comment_with_label "ENTER: cweld" (node_in, weldbit) ("node_in", "weldbit")+ bb <- circ_if weldbit (+ cdoweld1 g t aa+ )(+ cdoweld0 f aa+ )+ t' <- cgate_not t+ let node_out = (t', bb)+ comment_with_label "EXIT: cweld" node_out "node_out"+ return node_out++-- | Input a node /a/ and return the left or right child of /a/+-- (depending on whether the /childbit/ is 'False' or 'True'. This+-- works for leaf and non-leaf nodes.+cchild :: Boollist -> Boollist -> CNode -> Bit -> Circ CNode+cchild f g node_in@(t, a:aa) childbit = do+ comment_with_label "ENTER: cchild" (node_in, childbit) ("node_in", "childbit")+ node_out <- circ_if a (+ -- This is a leaf+ cweld f g (t, a:aa) childbit+ )( + -- This is not a leaf+ cchildintree (t, a:aa) childbit+ )+ comment_with_label "EXIT: cchild" node_out "node_out"+ return node_out++cchild f g (t, _) childbit = + error "cchild: invalid node"++-- | Input a node address (without the tree bit) and return the parity+-- of the node level expressed as a boolean either 'False' or+-- 'True'. Leaves have parity 'False', and other levels have+-- alternating parities. In other words: count the number of leading+-- zeros modulo 2.+clevel_parity :: Bitlist -> Circ Bit+clevel_parity node = do+ comment_with_label "ENTER: clevel_parity" node "node"+ parity <- clevel_parity_rec node+ comment_with_label "EXIT: clevel_parity" parity "parity"+ return parity++ where+ clevel_parity_rec :: Bitlist -> Circ Bit+ clevel_parity_rec [] = cinit False+ clevel_parity_rec (h:t) = do+ r <- clevel_parity_rec t+ circ_if h (+ cinit False+ )(+ cgate_not r+ )++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node address is invalid. In other words, return 'True' iff the+-- list consists of all 0's.+cis_zero :: Bitlist -> Circ Bit+cis_zero node = do+ comment_with_label "ENTER: cis_zero" node "node"+ is_zero <- cis_zero_rec node+ comment_with_label "EXIT: cis_zero" is_zero "is_zero"+ return is_zero+ + where+ cis_zero_rec :: Bitlist -> Circ Bit+ cis_zero_rec [] = cinit True+ cis_zero_rec (h:t) = do+ circ_if h (+ cinit False+ )(+ cis_zero_rec t+ )++-- | Input a node address (without the tree bit) and return 'True' iff+-- the node is a root or invalid. In other words, check whether all+-- digits but the last are 0's.+cis_root :: Bitlist -> Circ Bit+cis_root node = do+ comment_with_label "ENTER: cis_root" node "node"+ is_root <- cis_root_rec node+ comment_with_label "EXIT: cis_root" is_root "is_root"+ return is_root++ where+ cis_root_rec :: Bitlist -> Circ Bit+ cis_root_rec [] = cinit True+ cis_root_rec (h:[]) = cinit True+ cis_root_rec (h:t) = do+ circ_if h (+ cinit False+ )(+ cis_root_rec t+ )++-- | @'cv_function' f g c a@: returns /v/[sub /c/](/a/), the label of the+-- node connected to /a/ by an edge of color /c/, or 'Nothing' if+-- there is no such node. The parameters /f/ and /g/ encode the+-- welding functions, and are lists of length /n/. /c/ is a color in+-- the range 0..3, and /a/ is an (/n/+2)-bit node label.+-- +-- We currently implement @'Maybe' 'CNode'@ as an indexed union, and+-- specifically as @('CNode','Bit')@. When /Bit/='True', the value of+-- 'CNode' is undefined (doesn't matter); in particular, this value+-- may contain garbage.+cv_function :: Boollist -> Boollist -> Int -> CNode -> Circ (CNode,Bit)+cv_function f g color a = do+ comment_with_label (printf "ENTER: cv_function (color=%d)" color) a "a"+ let (t,aa) = a+ bc_hi <- clevel_parity aa+ z <- cis_zero aa+ e <- cis_root aa+ let a1 = last aa+ let [c_hi', c_lo'] = boollist_of_int_bh 2 color+ c_hi <- cinit c_hi'+ c_lo <- cinit c_lo'+ cbc_hi <- cgate_xor [c_hi, bc_hi]+ let cbc_lo = c_lo+ not_e <- cgate_not e+ cbc_lo_eq_a1 <- cgate_eq cbc_lo a1+ cond1 <- cgate_and [not_e, cbc_hi, cbc_lo_eq_a1]+ (b, invalid) <- circ_if cond1 (+ do + cparent_a <- cparent a+ false <- cinit False+ return (cparent_a, false)+ )(+ do+ cchild_a_cbc_lo <- cchild f g a cbc_lo+ not_z <- cgate_not z+ cbc_hi_eq_false <- cgate_not cbc_hi+ valid <- cgate_and [not_z, cbc_hi_eq_false]+ not_valid <- cgate_not valid+ -- a slight optimization here: we return garbage in the+ -- first register if not_valid == True+ return (cchild_a_cbc_lo, not_valid)+ )+ comment_with_label (printf "EXIT: cv_function (color=%d)" color) (b, invalid) ("b", "invalid")+ return (b, invalid)++-- ======================================================================+-- *** Oracle abstraction++-- | The classical oracle implementation, packaged into the 'Oracle'+-- abstraction. This oracle has two parameters, namely the welding+-- vectors /f/ and /g/. Note: this oracle has not been optimized+-- whatsoever.+oracle_classical :: Boollist -> Boollist -> Oracle+oracle_classical f g =+ Oracle { n = n,+ m = m,+ k = k,+ entrance = entrance,+ oraclefun = oraclefun+ } where+ n = length f+ m = n+2+ k = 4+ entrance = boollist_of_int_bh m 1+ + oraclefun :: Int -> (Qulist, Qulist, Qubit) -> Circ ()+ oraclefun color (a,b,r) = do+ let an = qnode_of_qulist a+ let bn = qnode_of_qulist b+ (classical_to_quantum . classical_to_reversible) (cv_function f g color) (an, (bn, r))+ return ()+ +-- ======================================================================+-- * Testing functions++-- | Output the list of colored edges as computed by the classical+-- 'v_function', for some arbitrary choice of /f/ and /g/ and /n/=3.+main_edges1 :: IO()+main_edges1 = mapM_ output (sample_all0 (127,3))+ where+ f = take 5 (True : False : f) + g = take 5 (False : True : g)+ + output :: (Int,Int) -> IO()+ output (a,c) =+ case v_function f g c (node_of_int 7 a) of+ Nothing -> printf "%d ---%d---> None\n" a c+ Just b -> printf "%d ---%d---> %d\n" a c (int_of_node b)++-- | For debugging: 'circfun' is similar to 'v_function', except it+-- works by calling 'cv_function' to assemble the circuit, then+-- simulates it. This is for testing whether the assembled circuit is+-- correct. Returns @('Bool', 'Node')@ instead of @'Maybe' 'Node'@, so+-- that we can see any garbage that is output in case of an invalid+-- node.+circfun :: Boollist -> Boollist -> Int -> Node -> (Node, Bool)+circfun f g color nd = + run_classical_generic (cv_function f g color) nd++-- | Output the list of colored edges as computed by simulating the+-- circuit 'cv_function', for some arbitrary choice of /f/ and /g/ and+-- /n/=3. This is like 'main_edges1', except it actually assembles and+-- simulates the classical circuit.+main_edges2 :: IO()+main_edges2 = mapM_ output (sample_all0 (127,3))+ where+ f = take 5 (True : False : f) + g = take 5 (False : True : g)+ output :: (Int,Int) -> IO()+ output (a,c) =+ case circfun f g c (node_of_int 7 a) of+ (node, False) -> printf "%d ---%d---> %d\n" a c (int_of_node node)+ (garbage, True) -> printf "%d ---%d---> None (%d)\n" a c (int_of_node garbage)+ +-- | Graphically output the classical oracle circuit for color /c/,+-- using /n/ from the oracle data structure, and for some arbitrary+-- /f/ and /g/.+main_oraclec :: Format -> BWT.Oracle -> Int -> IO()+main_oraclec format oracle color =+ print_generic format circuit cnode_shape+ where+ m' = BWT.m oracle+ n' = BWT.n oracle+ f = take n' (True : False : f)+ g = take n' (False : True : g)+ cnode_shape = cnode_of_bitlist (replicate m' bit)+ circuit n = cv_function f g color n++-- | Like 'main_oraclec', except it rewrites the classical circuit in+-- terms of Toffoli gates.+main_oracle2 :: Format -> BWT.Oracle -> Int -> IO()+main_oracle2 format oracle color =+ print_generic format circuit cnode_shape+ where+ m' = BWT.m oracle+ n' = BWT.n oracle+ f = take n' (True : False : f)+ g = take n' (False : True : g)+ cnode_shape = cnode_of_bitlist (replicate m' bit)+ circuit n = classical_to_cnot (cv_function f g color n)++-- | Like 'main_oraclec', except it makes the classical circuit+-- reversible first.+main_oracle3 :: Format -> BWT.Oracle -> Int -> IO()+main_oracle3 format oracle color =+ print_generic format circuit (cnode_shape, (cnode_shape, qubit))+ where+ m' = BWT.m oracle+ n' = BWT.n oracle+ f = take n' (True : False : f)+ g = take n' (False : True : g)+ cnode_shape = qnode_of_qulist (replicate m' qubit)+ circuit = (classical_to_quantum . classical_to_reversible) (cv_function f g color)++-- | Output the top-level circuit for the binary welded tree algorithm+-- with the classical oracle, using some arbitrary welding vectors /f/+-- and /g/, and /s/=1.+main_qrwbwt :: IO()+main_qrwbwt =+ print_simple EPS (qrwbwt (oracle_classical f g) dt 1)+ where + f = [False, False, True]+ g = [True, False, True]+ dt = pi/180
@@ -0,0 +1,604 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Algorithms/BWT/BWT.hs" #-}+-- | This module provides an implementation of the main binary welded+-- tree algorithm and oracle, using a more-or-less imperative+-- programming style. We abstract the oracle into a data type, so that+-- different oracles can be plugged into the main algorithm.++module Quipper.Algorithms.BWT.BWT where++-- import other Quipper stuff+import Quipper+import Quipper.Algorithms.BWT.Definitions++import Quipper.Libraries.Qureg+import Quipper.Libraries.Decompose++import Quipper.Utils.Auxiliary++import Text.Printf++-- ======================================================================+-- * Oracle abstraction++-- | A data structure to hold an oracle. The binary welded tree+-- algorithm is parametric on an oracle. An oracle encodes a graph,+-- and provides the following information: the tree depth /n/ (in the+-- above example: 3), the label length /m/ (in bits; 5 in the above+-- example), the number of edge colors /k/, the entrance label+-- /ENTRANCE/, and for each color 0 ≤ /c/ < /k/, a reversible circuit+-- /ORACLE/[sub /c/](/a/,/b/,/r/). On basis vectors, this circuit+-- encodes the edge information in the following sense:+-- +-- > ORACLE[sub c](a, b, r) = (a, b ⊕ v[sub c](a), r ⊕ f[sub c](a)),+-- +-- where /f/[sub /c/](/a/) is 1 if the node /a/ is connected to an+-- edge of color /c/, and 0 otherwise; and /v/[sub /c/](a) is the+-- node label connected to node /a/ along an edge of color /c/ (if+-- any), and arbitrary otherwise. +-- +-- Not all available node labels need to be used (for example, 0 and+-- 16 are unused in the graph in the above illustration).++data Oracle = Oracle {+ n :: Int,+ m :: Int,+ k :: Int,+ entrance :: Boollist,+ oraclefun :: Int -> (Qureg, Qureg, Qubit) -> Circ ()+}++-- ======================================================================+-- * Top-level algorithm++-- | The main loop of the binary welded tree algorithm. +-- +-- @qrwbwt oracle s dt@: Do a quantum random walk on the binary welded+-- tree given by the oracle /oracle/, for /s/ times steps of length+-- /dt/. Returns a bit list corresponding to the computed exit node+-- label.++qrwbwt :: Oracle -> Int -> Timestep -> Circ [Bit]+qrwbwt oracle s dt = do+ comment (printf "ENTER: qrwbwt (s=%d, dt=%.3e)" s dt)+ -- initialize a to the entrance label+ a <- qinit_register (entrance oracle)+ with_ancilla_reg (m oracle) $ \b -> do+ with_ancilla $ \r -> do+ loopM_boxed_if (s > 1) "qrwbwt_loop" s (a,b,r) $ \(a,b,r) -> do+ for 0 (k oracle-1) 1 $ \c -> do+ (oraclefun oracle) c (a, b, r)+ timestep (a, b, r, dt, m oracle)+ (oraclefun oracle) c (a, b, r)+ endfor+ return (a,b,r)+ endfor+ exit <- qmeasure_register a+ comment_with_label "EXIT: qrwbwt" exit "exit"+ return exit++-- | @timestep (a, b, r, dt, m)@: Perform a single time step /dt/ of+-- the quantum walk. This is done by iterating through each of the+-- available edge colors, and performing a diffusion step for each+-- color. Here, /a/ is an /m/-qubit registers holding (a superposition+-- of) the current node label. /b/ is an /m/-qubit ancilla register,+-- and /r/ is an ancilla qubit. Both /b/ and /r/ are expected to be+-- initialized to |0〉 by the caller, and will be returned in state+-- |0〉.+timestep :: (Qureg, Qureg, Qubit, Timestep, Int) -> Circ ()+timestep (a, b, r, dt, m) = do+ comment_with_label "ENTER: timestep" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ for 0 (m-1) 1 $ \i -> do+ wGate (a.!(i), b.!(i))+ endfor+ for 0 (m-1) 1 $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ controlledExpGate (dt, r, h)+ for (m-1) 0 (-1) $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ for (m-1) 0 (-1) $ \i -> do+ wGateInverse (a.!(i), b.!(i))+ endfor+ comment_with_label "EXIT: timestep" (a,b,r) ("a","b","r")+ return ()++-- ======================================================================+-- * Oracle implementation++-- $ The functions in this section implement a particular oracle for a+-- binary welded tree. The oracle is parametric on:+-- +-- * the tree depth /n/;+-- +-- * two \"welding vectors\" /f/ and /g/, specifying how the leaves of+-- the two binary trees are connected to each other. Specifically, /f/+-- and /g/ encode the permutations of leaves given by a ↦ a ⊕ f and +-- a ↦ a + g, respectively, where \"⊕\" denotes bitwise exclusive or,+-- and \"+\" denotes binary addition.++-- ----------------------------------------------------------------------+-- ** Oracle subroutines++-- | The top-level oracle circuit. The arguments are of the form (/a/,+-- /b/, /r/, /color/, /f/, /g/, /n/), where /a/, /b/ are quantum+-- registers of length /n/+2, /color/ is a boolean register of length+-- 2, and /f/ and /g/ are boolean registers of length /n/.+oracle :: (Qureg, Qureg, Qubit, Boolreg, Boolreg, Boolreg, Int) -> Circ ()+oracle (a, b, r, color, f, g, n) = do+ let c = int_of_boolreg_unsigned_le color :: Int+ comment_with_label (printf "ENTER: oracle (color=%d)" c) (a,b,r) ("a","b","r")+ with_ancilla $ \root -> do+ with_ancilla $ \even -> do+ with_ancilla $ \isparent -> do+ with_ancilla $ \ischild -> do+ with_ancilla $ \direction -> do+ with_ancilla $ \ismatch -> do+ parseNodeRoot (a, root, even, n)+ parseNodeEven (a, even, n)+ testIsParent (a, root, even, isparent, color, n, 1, ismatch)+ testIsChild (even, ischild, direction, color, n)+ setParent (a, b, isparent, n)+ setChild (a, b, ischild, direction, f, g, n)+ with_controls (isparent .==. 0 .&&. ischild .==. 0) $ do {+ qnot_at r+ }+ testIsChild (even, ischild, direction, color, n)+ testIsParent (a, root, even, isparent, color, n, 0, ismatch)+ parseNodeEven (a, even, n)+ parseNodeRoot (a, root, even, n)+ comment_with_label (printf "EXIT: oracle (color=%d)" c) (a,b,r) ("a","b","r")+ return ()++-- | Input a node label /a/ of length at least /n/+1. Negate both+-- /root/ and /even/ if /a/ is a root node.+parseNodeRoot :: (Qureg, Qubit, Qubit, Int) -> Circ ()+parseNodeRoot (a, root, even, n) = do+ comment_with_label "ENTER: parseNodeRoot" (a, root, even) ("a", "root", "even")+ with_ancilla_reg (n+1) $ \scratch -> do+ for n 1 (-1) $ \index -> do + with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ endfor+ with_controls (scratch.!(0) .==. 0) $ do {+ qnot_at root;+ qnot_at even+ }+ for 1 n 1 $ \index -> do + with_controls (scratch.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index - 1))+ }+ with_controls (scratch.!(index) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1))+ }+ endfor+ comment_with_label "EXIT: parseNodeRoot" (a, root, even) ("a", "root", "even")+ return ()+ +-- | Input a node label /a/ of length at least /n/+1. Negate /even/+-- if the node /a/ occurs at an even height in the tree.+parseNodeEven :: (Qureg, Qubit, Int) -> Circ ()+parseNodeEven (a, even, n) = do+ comment_with_label "ENTER: parseNodeEven" (a, even) ("a", "even")+ with_ancilla_reg (n+1) $ \scratch -> do+ for n 1 (-1) $ \index -> do+ with_controls (scratch.!(n) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1));+ with_controls (Prelude.even index) $ do {+ qnot_at even+ }+ }+ with_controls (scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(n))+ }+ endfor+ for 1 n 1 $ \index -> do+ with_controls (scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(n))+ } + with_controls (scratch.!(n) .==. 0 .&&. a.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index-1))+ }+ endfor+ comment_with_label "EXIT: parseNodeEven" (a, even) ("a", "even")+ return ()++-- | Input a node label /a/ of length at least 1, and flags /root/+-- and /even/ describing whether /a/ is a root and at an even level,+-- respectively. Negate /isparent/ if /a/ has a parent of color+-- /color/ in the tree. +-- +-- The qubit /ismatch/ is an ancilla, and /really/ is either 0 or+-- 1. They are jointly used to control uncomputation, so that the+-- following sequence will compute and then uncompute 'testIsParent':+-- +-- > ismatch <- qinit 0+-- > testIsParent (a, root, even, isparent, color, n, 1, ismatch)+-- > testIsParent (a, root, even, isparent, color, n, 0, ismatch)+-- > qterm 0 ismatch+testIsParent :: (Qureg, Qubit, Qubit, Qubit, Boolreg, Int, Int, Qubit) -> Circ ()+testIsParent (a, root, even, isparent, color, n, really, ismatch) = do+ let c = int_of_boolreg_unsigned_le color :: Int+ comment_with_label (printf "ENTER: testIsParent (color=%d really=%d)" c really) (a, root, even, isparent, ismatch) ("a", "root", "even", "isparent", "ismatch")+ with_controls (really == 0) $ do {+ with_controls (root .==. 0 .&&. ismatch .==. 1) $ do {+ qnot_at isparent+ }+ }+ if color.!(1) == 1+ then+ if color.!(0) == 1 then+ with_controls (even .==. 1 .&&. a.!(0) .==. 1) $ do {+ qnot_at ismatch+ }+ else+ with_controls (even .==. 1 .&&. a.!(0) .==. 0) $ do {+ qnot_at ismatch+ }+ else+ if color.!(0) == 1 then+ with_controls (even .==. 0 .&&. a.!(0) .==. 1) $ do {+ qnot_at isparent+ }+ else+ with_controls (even .==. 0 .&&. a.!(0) .==. 0) $ do {+ qnot_at isparent+ }+ with_controls (root .==. 0 .&&. ismatch .==. 1) $ do {+ qnot_at isparent+ }+ comment_with_label (printf "EXIT: testIsParent (color=%d really=%d)" c really) (a, root, even, isparent, ismatch) ("a", "root", "even", "isparent", "ismatch")+ return ()++-- | Consider a node /a/, and negate /ischild/ if /a/ has a child+-- node of color /color/. Also set /direction/ to indicate whether+-- it is a \"left\" or \"right\" child. Here, /color/ is a boolean+-- register of length 2, representing a color. This function is+-- self-inverse.+testIsChild :: (Qubit, Qubit, Qubit, Boolreg, Int) -> Circ ()+testIsChild (even, ischild, direction, color, n) = do+ comment_with_label "ENTER: testIsChild" (even, ischild, direction) ("even", "ischild", "direction")+ if color.!(1) == 1+ then+ with_controls (even .==. 0) $ do {+ qnot_at ischild+ }+ else+ with_controls (even .==. 1) $ do {+ qnot_at ischild+ }+ with_controls (color.!(0) == 1) $ do {+ qnot_at direction+ }+ comment_with_label "EXIT: testIsChild" (even, ischild, direction) ("even", "ischild", "direction")+ return ()++-- | Input a node label /a/ of length at least /n/+2, and a flag+-- /isparent/ that has been initialized accordingly. Also input a+-- register /b/ of length at least /n/+2, initialized to |0〉. If+-- /isparent/ is set, set /b/ to the node label of the parent of+-- /a/. This is self-inverse.+setParent :: (Qureg, Qureg, Qubit, Int) -> Circ ()+setParent (a, b, isparent, n) = do+ comment_with_label "ENTER: setParent" (a, b, isparent) ("a", "b", "isparent")+ for 0 (n-1) 1 $ \index -> do+ with_controls (isparent .==. 1 .&&. a.!(index+1) .==. 1) $ do {+ qnot_at (b.!(index))+ }+ endfor+ with_controls (isparent .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at (b.!(n+1))+ }+ comment_with_label "EXIT: setParent" (a, b, isparent) ("a", "b", "isparent")+ return ()++-- | Similar to 'setParent', but set /b/ to the node label of the+-- indicated child of /a/. Here /a/ and /b/ are quantum registers of+-- length at least /n/+2, and /f/ and /g/ are boolean registers of+-- length /n/.+setChild :: (Qureg, Qureg, Qubit, Qubit, Boolreg, Boolreg, Int) -> Circ ()+setChild (a, b, ischild, direction, f, g, n) = do+ comment_with_label "ENTER: setChild" (a, b, ischild, direction) ("a", "b", "ischild", "direction")+ with_ancilla $ \childctrl -> do+ with_controls (ischild .==. 1 .&&. a.!(n) .==. 1) $ do {+ qnot_at childctrl+ }+ setWeld (a, b, childctrl, direction, f, g, n)+ with_controls (ischild .==. 1) $ do {+ qnot_at childctrl+ }+ setChildInTree (a, b, childctrl, direction, n)+ with_controls (ischild .==. 1 .&&. a.!(n) .==. 0) $ do {+ qnot_at childctrl+ }+ comment_with_label "EXIT: setChild" (a, b, ischild, direction) ("a", "b", "ischild", "direction")+ return ()+ +-- | A special case of 'setChild', where the child is inside the same+-- binary tree (i.e., not via the welding). +setChildInTree :: (Qureg, Qureg, Qubit, Qubit, Int) -> Circ ()+setChildInTree (a, b, childctrl, direction, n) = do+ comment_with_label "ENTER: setChildInTree" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ with_controls (childctrl .==. 1 .&&. direction .==. 1) $ do {+ qnot_at (b.!(0))+ }+ for 1 n 1 $ \index -> do+ with_controls (childctrl .==. 1 .&&. a.!(index-1) .==. 1) $ do {+ qnot_at (b.!(index))+ }+ endfor+ with_controls (childctrl .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at (b.!(n+1))+ }+ comment_with_label "EXIT: setChildInTree" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ return ()++-- | A special case of 'setChild', where the child is in the opposite+-- binary tree, i.e., we follow one of the welding edges.+setWeld :: (Qureg, Qureg, Qubit, Qubit, Boolreg, Boolreg, Int) -> Circ ()+setWeld (a, b, childctrl, direction, f, g, n) = do+ comment_with_label "ENTER: setWeld" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ with_ancilla $ \weldctrl -> do+ with_controls (childctrl .==. 1 .&&. direction .==. 0) $ do {+ qnot_at weldctrl+ }+ doWeld0 (a, b, weldctrl, f, n)+ with_controls (childctrl .==. 1) $ do {+ qnot_at weldctrl+ }+ doWeld1 (a, b, weldctrl, g, n)+ with_controls (childctrl .==. 1 .&&. direction .==. 1) $ do {+ qnot_at weldctrl+ }+ with_controls (childctrl .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at (b.!(n+1))+ }+ with_controls (childctrl .==. 1) $ do {+ qnot_at (b.!(n));+ qnot_at (b.!(n+1))+ }+ comment_with_label "EXIT: setWeld" (a, b, childctrl, direction) ("a", "b", "childctrl", "direction")+ return ()++-- | Input a node label /a/, and a register /b/ initialized to+-- |0〉. If /weldctrl/ is set, set /b/ to the node connected to /a/+-- by the welding function /f/. This is self-inverse. Here, /a/ and+-- /b/ are quantum registers of length at least /n/+2, and /f/ is a+-- boolean register of length /n/.+doWeld1 :: (Qureg, Qureg, Qubit, Boolreg, Int) -> Circ ()+doWeld1 (a, b, weldctrl, g, n) = do+ comment_with_label "ENTER: doWeld1" (a, b, weldctrl) ("a", "b", "weldctrl")+ with_ancilla $ \addsub -> do+ with_controls (weldctrl .==. 1 .&&. a.!(n+1) .==. 0) $ do {+ qnot_at addsub+ }+ cAddNum (addsub, b, a, g, n)+ with_controls (weldctrl .==. 1) $ do {+ qnot_at addsub+ }+ cSubNum (addsub, b, a, g, n)+ with_controls (weldctrl .==. 1 .&&. a.!(n+1) .==. 1) $ do {+ qnot_at addsub+ }+ comment_with_label "EXIT: doWeld1" (a, b, weldctrl) ("a", "b", "weldctrl")+ return ()++-- | Input a node label /a/, and a register /b/ initialized to+-- |0〉. If /weldctrl/ is set, set /b/ to the node connected to /a/+-- by the welding function /g/. This is self-inverse. Here, /a/ and+-- /b/ are quantum registers of length at least /n/+2, and /g/ is a+-- boolean register of length /n/.+doWeld0 :: (Qureg, Qureg, Qubit, Boolreg, Int) -> Circ ()+doWeld0 (a, b, weldctrl, f, n) = do+ comment_with_label "ENTER: doWeld0" (a, b, weldctrl) ("a", "b", "weldctrl")+ for 0 (n-1) 1 $ \index -> do+ with_controls (weldctrl .==. 1) $ do {+ qnot_at (b.!(index)) `controlled` a.!(index) ./=. f.!(index)+ }+ endfor+ comment_with_label "EXIT: doWeld0" (a, b, weldctrl) ("a", "b", "weldctrl")+ return ()++-- | This function implements integer addition. Input a quantum+-- register /input/ and a boolean register /num/, representing+-- integers, and a quantum register /out/ initialized to |0〉. If+-- /control/ is set, set /out/ to /input/ + /num/, otherwise do+-- nothing. Here /input/ and /out/ are quantum registers of length at+-- least /n/, /num/ is a boolean register of length /n/.+cAddNum :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cAddNum (control, out, input, num, n) = do+ comment_with_label "ENTER: cAddNum" (control, out, input) ("control", "out", "input")+ -- we represent mask as 1 << maskbit+ with_ancilla_reg n $ \scratch -> do+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(0) .==. 1) $ do {+ qnot_at (out.!(0))+ }+ with_controls (num.!(maskbit) /= 0) $ do {+ with_controls (control .==. 1) $ do {+ qnot_at (out.!(0))+ };+ with_controls (input.!(0) .==. 1) $ do {+ qnot_at (scratch.!(0))+ }+ }+ for 1 (n-1) 1 $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(index) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. control .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (control .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ cAddNumClear (control, scratch, input, num, n)+ comment_with_label "EXIT: cAddNum" (control, out, input) ("control", "out", "input")+ return ()++-- | A helper function for clearing the scratch space used by 'cAddNum'.+cAddNumClear :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cAddNumClear (control, scratch, input, num, n) = do+ comment_with_label "ENTER: cAddNumClear" (control, scratch, input) ("control", "scratch", "input")+ -- we represent mask as 1 << maskbit+ for (n-1) 1 (-1) $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. input.!(0) .==. 1) $ do {+ qnot_at (scratch.!(0))+ }+ comment_with_label "EXIT: cAddNumClear" (control, scratch, input) ("control", "scratch", "input")+ return ()++-- | Like 'cAddNum', except subtract instead of adding. +cSubNum :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cSubNum (control, out, input, num, n) = do+ comment_with_label "ENTER: cSubNum" (control, out, input) ("control", "out", "input")+ -- we represent mask as 1 << maskbit+ with_ancilla_reg n $ \scratch -> do+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(0) .==. 1) $ do {+ qnot_at (out.!(0))+ }+ with_controls (num.!(maskbit) /= 0) $ do {+ with_controls (control .==. 1) $ do {+ qnot_at (out.!(0))+ };+ with_controls (input.!(0) .==. 0) $ do {+ qnot_at (scratch.!(0))+ }+ }+ for 1 (n-1) 1 $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (control .==. 1 .&&. input.!(index) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. control .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (control .==. 1 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (out.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 0) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ cSubNumClear (control, scratch, input, num, n)+ comment_with_label "EXIT: cSubNum" (control, out, input) ("control", "out", "input")+ return ()++-- | A helper function for clearing the scratch space used by 'cSubNum'.+cSubNumClear :: (Qubit, Qureg, Qureg, Boolreg, Int) -> Circ ()+cSubNumClear (control, scratch, input, num, n) = do+ comment_with_label "ENTER: cSubNumClear" (control, scratch, input) ("control", "scratch", "input")+ -- we represent mask as 1 << maskbit+ for (n-1) 1 (-1) $ \index -> do+ let maskbit = index -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (input.!(index) .==. 0 .&&. scratch.!(index-1) .==. 1) $ do {+ qnot_at (scratch.!(index))+ }+ with_controls (num.!(maskbit) /= 0 .&&. input.!(index) .==. 0) $ do {+ qnot_at (scratch.!(index))+ }+ endfor+ let maskbit = 0 -- invariant: mask = 1 << maskbit+ with_controls (num.!(maskbit) /= 0 .&&. input.!(0) .==. 0) $ do {+ qnot_at (scratch.!(0))+ }+ comment_with_label "EXIT: cSubNumClear" (control, scratch, input) ("control", "scratch", "input")+ return ()++-- ----------------------------------------------------------------------+-- ** The oracle data structure++-- | This function inputs two welding functions /f/ and /g/, and+-- returns the oracle defined by the preceding functions. +-- +-- We call this the \"orthodox\" oracle, because the implementation+-- follows its specification very closely. For example, it uses a very+-- \"imperative\" programming style. For alternative implementations+-- of this and other oracles, see the modules+-- "Quipper.Algorithms.BWT.Alternative" and "Quipper.Algorithms.BWT.Template".+oracle_orthodox :: Boollist -> Boollist -> Oracle+oracle_orthodox f g =+ Oracle { n = n,+ m = m,+ k = k,+ entrance = entrance,+ oraclefun = oraclefun+ } where+ n = length f+ m = n+2+ k = 4+ entrance = boollist_of_int_bh m 1+ f_reg = boolreg_of_boollist_te f+ g_reg = boolreg_of_boollist_te g+ + oraclefun :: Int -> (Qureg, Qureg, Qubit) -> Circ ()+ oraclefun c (a,b,r) = do+ let color = boolreg_of_int_le 2 c+ oracle (a, b, r, color, f_reg, g_reg, n)+ return ()++-- ======================================================================+-- * Main functions++-- These functions are so that the user can output something.++-- | Output the circuit for the quantum walk and a binary welded tree,+-- for the given 'Oracle' in the specified 'Format' and using the+-- specified 'GateBase'. Use /s/ time steps of length /dt/.+main_circuit :: Format -> GateBase -> Oracle -> Int -> Timestep -> IO()+main_circuit format base oracle s dt =+ print_generic format (decompose_generic base circuit)+ where+ circuit = qrwbwt oracle s dt++-- | Output the circuit for the given 'Oracle' and the given color+-- (specified as an 'Int'). Use the specified output 'Format' and+-- 'GateBase'.+main_oracle :: Format -> GateBase -> Oracle -> Int -> IO()+main_oracle format base oracle c =+ let m' = m oracle + ofun = oraclefun oracle+ circuit = (\(a,b,r) -> ofun c (qureg_of_qulist_te a, qureg_of_qulist_te b, r))+ in+ print_generic format (decompose_generic base circuit) (replicate m' qubit, replicate m' qubit, qubit)
@@ -0,0 +1,39 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Algorithms/BWT/Definitions.hs" #-}+-- | This module provides some convenient definitions for the Binary+-- Welded Tree algorithm implementation.++module Quipper.Algorithms.BWT.Definitions where++import Quipper++-- ======================================================================+-- * Some convenient gates++-- | Apply the binary /W/-gate to a pair of qubits. The W-gate+-- diagonalizes the SWAP operation.+wGate :: (Qubit, Qubit) -> Circ ()+wGate (a,b) = do+ gate_W a b+ return ()++-- | Apply the /inverse/ of the /W/-gate. Note: since the /W/-gate is+-- self-inverse, this is really the same as 'wGate'. However, we+-- define this as a separate function for clarity. +wGateInverse :: (Qubit, Qubit) -> Circ ()+wGateInverse = wGate++-- | Apply a doubly-controlled not gate to a triple of qubits (/a/,+-- /b/, /c/). Here the qubit /c/ is negated if /a/=1 and /b/=0.+toffoliGate :: (Qubit, Qubit, Qubit) -> Circ ()+toffoliGate (a, b, c) =+ qnot_at c `controlled` (a .==. 1 .&&. b .==. 0)++-- | @controlledExpGate(t, r, h):@+-- Apply the [exp −/iZt/] gate to the qubit /h/, provided that /r/=0. +controlledExpGate :: (Timestep, Qubit, Qubit) -> Circ ()+controlledExpGate (t, r, h) = do+ expZt t h `controlled` (r .==. 0)+ return ()
@@ -0,0 +1,89 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/SimpleOracleSimulation.hs" #-}+-- | A test file to simulate various decompositions of the simple oracle circuit,+-- from the BWT algorithm.++import Quipper+import Quipper.Libraries.Simulation+import Quipper.Libraries.Decompose++-- import other Quipper stuff+import Quipper.Algorithms.BWT.Alternative+import Quipper.Utils.Auxiliary++-- | Extract the circuit from an oracle.+oracleCircuit :: Oracle -> Int -> Int -> Circ (Qubit,[Qubit])+oracleCircuit oracle color i = do+ input <- qinit (boollist_of_int_bh (m oracle) i)+ output <- qinit (boollist_of_int_bh (m oracle) 0)+ q <- qinit False+ oraclefun oracle color (input,output,q)+ return (q, output)+ +-- | Run the simple oracle with a given decomposition, and given inputs.+run_simple' :: GateBase -> Int -> Int -> IO (Bool,Int)+run_simple' gb color i = do (b,bs) <- run_generic_io (undefined :: Double) (decompose_generic gb (oracleCircuit oracle_simple color i))+ return (b, int_of_boollist_unsigned_bh bs)++-- | Run the simple oracle with a given decomposition, and given inputs, and print the result in a more readable manner.+run_simple :: GateBase -> Int -> Int -> IO ()+run_simple gb color i = do (b,bs) <- run_simple' gb color i+ if not b + then putStrLn (show i ++ " --( " ++ show color ++ " )--> " ++ show bs)+ else return ()++-- | Run the simple oracle with a given decomposition, mapped over all possible inputs.+main_run' :: GateBase -> IO ()+main_run' gb = mapM_ (\(x,y) -> run_simple gb x y) [(x,y) | y <- [0..31], x <- [0..3]]++-- | Run each decomposition of the oracle circuit and print out the resulting edges.+main_run :: IO ()+main_run = do putStrLn "Logical"+ main_run' Logical+ putStrLn "Toffoli"+ main_run' Toffoli+ putStrLn "Binary"+ main_run' Binary ++-- | Simumlate the simple oracle with a given decomposition, and given inputs.+sim_simple' :: GateBase -> Int -> Int -> ProbabilityDistribution Double (Bool,Int)+sim_simple' gb color i = do (b,bs) <- sim_generic undefined (decompose_generic gb (oracleCircuit oracle_simple color i))+ return (b, int_of_boollist_unsigned_bh bs)++-- | Simulate the simple oracle with a given decomposition,+-- and given inputs, and print the result in a more readable manner.+sim_simple :: GateBase -> Int -> Int -> ProbabilityDistribution Double (IO ())+sim_simple gb color i = do (b,bs) <- sim_simple' gb color i+ if not b + then return $ putStr (show i ++ " --( " ++ show color ++ " )--> " ++ show bs)+ else Vector [(return (),0.0)]++sequenceP :: ProbabilityDistribution Double (IO ()) -> IO ()+sequenceP (Vector []) = return ()+sequenceP (Vector ((io,prob):ps)) = do if prob /= 0.0 then do io+ putStrLn (" - " ++ show prob)+ else return ()+ sequenceP (Vector ps) ++-- | Simulate the simple oracle with a given decomposition, mapped over all possible inputs.+main_sim' :: GateBase -> IO ()+main_sim' gb = mapM_ (\(x,y) -> sequenceP (sim_simple gb x y)) [(x,y) | y <- [0..31], x <- [0..3]]++main_sim'' :: GateBase -> Int -> Int -> IO ()+main_sim'' gb x y = sequenceP (sim_simple gb x y)++-- | Simulate each decomposition of the oracle circuit and print out the resulting edges.+main_sim :: IO ()+main_sim = do putStrLn "Logical"+ main_sim' Logical+ putStrLn "Toffoli"+ main_sim' Toffoli+ putStrLn "Binary"+ main_sim' Binary ++main :: IO ()+main = do main_run+ main_sim+
@@ -0,0 +1,34 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/SimulationTest.hs" #-}+import Quipper+import Quipper.Libraries.Simulation+import System.Random++circuit :: (Qubit, Qubit) -> Circ (Qubit, Qubit)+circuit (q,r) = do+ with_computed code $ \x -> do+ qnot r `controlled` [r,x]+ hadamard r+ return (q,r)++ where+ code = do+ s <- cinit False+ s <- prepare s+ hadamard q+ qnot s `controlled` q+ ++circuit2 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+circuit2 (s,q,r) = do+ circuit (q,r) `controlled` s+ return (s,q,r)++main =+ print_simple Preview circuit2+ +main2 = do+ g <- newStdGen+ print $ run_generic g (0.0 :: Double) circuit2 (True,True,True)
@@ -0,0 +1,110 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/SynthesisTest.hs" #-}+-- | Some demos for "Quipper.Libraries.Synthesis".++import Quipper+import Quipper.Libraries.Synthesis++import Quantum.Synthesis.Ring+import Quantum.Synthesis.Matrix+import Quantum.Synthesis.MultiQubitSynthesis++import System.Random++-- ----------------------------------------------------------------------+-- * Some demos for Quipper.Libraries.Synthesis++-- | Import a compressed Clifford+/T/ operator as a Quipper circuit.+main1 :: IO ()+main1 = do+ print_simple Preview (exact_synthesis1 (0x1d00d27a0188b095b8cdd4ead9a244198d8b22e :: Integer))+ +-- | Exact synthesis of a Clifford+/T/ circuit from an exact matrix+-- representation.+main2 :: IO ()+main2 = do+ print_simple Preview (exact_synthesis1 op)+ where+ op :: Matrix Two Two DOmega+ op = roothalf^4 * matrix2x2 ( 1 - 2*roottwo, 2 + roottwo - i )+ ( -2 - roottwo - i, 1 - 2*roottwo )++-- | Exact synthesis of a multi-qubit Clifford+/T/ circuit from an+-- exact matrix representation.+main3 :: IO ()+main3 = do+ print_generic Preview (exact_synthesis_alt op) [qubit, qubit]+ where+ op :: Matrix Four Four DOmega+ op = matrix4x4 ( 1, 0, 0, 0 )+ ( 0, -s, s, 0 )+ ( 0, 0, 0, 1 )+ ( 0, s, s, 0 ) + s = roothalf+ +-- | Exact synthesis of a multi-qubit Clifford+/T/ circuit from an+-- exact matrix representation.+main3a :: IO ()+main3a = do+ print_generic Preview (exact_synthesis_alt op) [qubit, qubit, qubit]+ where+ op :: Matrix Eight Eight DOmega+ op = matrix [[ 1, 0, 0, 0, 0, 0, 0, 0 ],+ [ 0, s, -s, 0, 0, 0, 0, 0 ],+ [ 0, 0, 0, 1, 0, 0, 0, 0 ],+ [ 0, s, s, 0, 0, 0, 0, 0 ],+ [ 0, 0, 0, 0, 1, 0, 0, 0 ],+ [ 0, 0, 0, 0, 0, 1, 0, 0 ],+ [ 0, 0, 0, 0, 0, 0, 0, 1 ],+ [ 0, 0, 0, 0, 0, 0, 1, 0 ]] + s = roothalf+ +-- | Approximate synthesis of a /z/-rotation as a Clifford+/T/ circuit.+-- Angle θ = π\/128, precision ε = 10[sup −30].+main4 :: IO ()+main4 = do+ g <- newStdGen -- a source of randomness+ print_simple Preview (approximate_synthesis_zrot prec (pi/128) g)+ where+ prec = 30 * digits++-- | Approximate synthesis of a global phase. +-- Angle α = π\/128, precision ε = 10[sup −30].+main5 :: IO ()+main5 = do+ g <- newStdGen -- a source of randomness+ print_simple Preview (approximate_synthesis_phase True prec (pi/128) g)+ where + prec = 30 * digits++-- | Approximate synthesis of an arbitrary single-qubit operator,+-- given by Euler angles. Precision ε = 2[sup −50].+main6 :: IO ()+main6 = do+ g <- newStdGen -- a source of randomness+ let circ = approximate_synthesis_euler True prec (alpha, beta, gamma, delta) g+ print_simple Preview circ+ where+ prec = 50 * bits+ alpha = 0.1 * pi+ beta = 0.2 * pi+ gamma = 0.5 * pi+ delta = -0.6 * pi+ +-- | Approximate synthesis of an arbitrary single-qubit operator,+-- given as a matrix. The matrix is given in an exact notation.+-- Precision ε = 10[sup −10].+main7 :: IO ()+main7 = do+ g <- newStdGen -- a source of randomness+ let circ = approximate_synthesis_u2 True prec op g+ print_simple Preview circ+ where+ prec = 10 * digits+ op = matrix2x2 ( 0.6, 0.8*i )+ (-0.8, 0.6*i )++-- | Run any of the above main functions:+main = main3a
@@ -0,0 +1,59 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Teleport.hs" #-}+import Quipper++plus_minus :: Bool -> Circ Qubit+plus_minus b = do+ q <- qinit b+ q <- hadamard q+ return q++share :: Qubit -> Circ (Qubit, Qubit)+share a = do+ b <- qinit False+ b <- qnot b `controlled` a+ return (a,b)++bell00 :: Circ (Qubit, Qubit)+bell00 = do+ a <- plus_minus False+ (a,b) <- share a+ return (a,b)++alice :: Qubit -> Qubit -> Circ (Bit,Bit)+alice q a = do+ a <- qnot a `controlled` q+ q <- hadamard q+ (x,y) <- measure (q,a)+ return (x,y)++bob :: Qubit -> (Bit,Bit) -> Circ Qubit+bob b (x,y) = do+ b <- gate_X b `controlled` y+ b <- gate_Z b `controlled` x+ cdiscard (x,y)+ return b++teleport :: Qubit -> Circ Qubit+teleport q = do+ (a,b) <- bell00+ (x,y) <- alice q a+ b <- bob b (x,y)+ return b++-- ----------------------------------------------------------------------+-- main functions++main_alice =+ print_simple Preview alice++main_bob =+ print_simple Preview bob++main_teleport =+ print_simple Preview teleport++main = main_teleport+
@@ -0,0 +1,174 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/TeleportGeneric.hs" #-}+import Quipper+import Quipper.Libraries.Simulation++import System.Random+import System.Environment+import System.CPUTime++plus_minus :: (QShape a qa ca) => a -> Circ qa+plus_minus a = do + qs <- qinit a+ qs <- mapUnary hadamard qs+ return qs++share :: (QShape a qa ca) => qa -> Circ (qa, qa)+share qa = do + qb <- qinit (qc_false qa)+ (qb, qa) <- mapBinary controlled_not qb qa+ return (qa, qb)++bell00 :: (QShape a qa ca) => a -> Circ (qa, qa)+bell00 shape = do + qa <- plus_minus shape+ (qa, qb) <- share qa+ return (qa, qb)++alice :: (QShape a qa ca) => qa -> qa -> Circ (ca,ca)+alice q a = do + (a, q) <- mapBinary controlled_not a q+ q <- mapUnary hadamard q+ (x,y) <- measure (q,a)+ return (x,y)++bob :: (QShape a qa ca) => qa -> (ca,ca) -> Circ qa+bob b (x,y) = do+ (b, y) <- mapBinary_c controlled_X b y+ (b, x) <- mapBinary_c controlled_Z b x+ cdiscard (x,y)+ return b+ where+ controlled_X b x = do+ gate_X b `controlled` x+ return (b,x)+ + controlled_Z b x = do+ gate_Z b `controlled` x+ return (b,x)+ +teleport :: (QData qa) => qa -> Circ qa+teleport q = do+ (a,b) <- bell00 (qc_false q)+ (x,y) <- alice q a+ b <- bob b (x,y)+ return b++teleport_labeled :: (QData qa) => qa -> Circ qa+teleport_labeled q = do+ comment_with_label "ENTER: teleport_labeled" q "q"+ comment "ENTER: bell00"+ (a,b) <- bell00 (qc_false q)+ comment_with_label "EXIT: bell00" (a,b) ("a","b")+ comment "ENTER: alice"+ (x,y) <- alice q a+ comment_with_label "EXIT: alice" (x,y) ("x","y")+ comment "ENTER: bob"+ b <- bob b (x,y)+ comment_with_label "EXIT: bob" b "b"+ comment "EXIT: teleport_labeled"+ return b++-- | A test that should help see how many qubits we can simulate+test_teleport :: [Bool] -> IO [Bool]+test_teleport = run_clifford_generic teleport++data What = Sim | Circ | Usage deriving Eq++-- | The main method deals with command line arguments, and timing of the simulation+main :: IO ()+main = do+ args <- getArgs+ if (length args /= 2) then usage else do+ let arg1 = head args+ let flag = case arg1 of+ "--sim" -> Sim+ "--circ" -> Circ + _ -> Usage+ if (flag == Usage) then usage else do + let arg = head (tail args)+ case reads arg of+ [(n,_)] -> do+ if (n < 0) then usage else do+ if (flag == Circ) then print_generic Preview teleport_labeled (replicate n qubit) else do+ input <- randomBools n+ putStrLn ("Input: " ++ show input)+ start <- getCPUTime+ output <- test_teleport input+ end <- getCPUTime+ putStrLn ("Output: " ++ show output)+ let time = end - start+ putStrLn ("Time: (" ++ show time ++ ")")+ show_time time+ _ -> usage++-- | Produce the given number of random boolean values+randomBools :: Int -> IO [Bool]+randomBools 0 = return []+randomBools n = do+ b <- randomIO+ bs <- randomBools (n-1)+ return (b:bs)++-- | Give a usage message if not being run from GHCI+usage :: IO ()+usage = do+ name <- getProgName+ if name == "<interactive>" then prompt else do+ putStrLn ("usage: " ++ name ++ " flag num_qubits")+ putStrLn (" where flag = --sim or --circ") ++-- | If we're in GHCI then we can prompt for the number of qubits to teleport+prompt :: IO ()+prompt = do+ putStrLn "Enter flag (--sim or --circ): "+ f <- getLine+ putStrLn "Enter number of qubits: "+ n <- getLine+ withArgs [f,n] main ++-- | Display an integer representing pico-seconds in a more readable format+show_time :: Integer -> IO ()+show_time t = case range t of+ Pico -> putStrLn (show t ++ " " ++ show Pico ++ ".")+ r -> do+ putStr (show (div t (ps' r)) ++ " " ++ show r ++ ", ")+ show_time (rem t (ps' r))++-- | Helper data-type for show_time function+data Range = Pico | Nano | Micro | Milli | Seconds | Minutes | Hours | Days+ deriving Eq++instance Show Range where+ show Pico = "picoseconds"+ show Nano = "nanoseconds"+ show Micro = "microseconds"+ show Milli = "milliseconds"+ show Seconds = "seconds"+ show Minutes = "minutes"+ show Hours = "hours"+ show Days = "days"++-- | Helper function for show_time function+ps' :: Range -> Integer+ps' Pico = 1+ps' Nano = 10^3 * ps' Pico+ps' Micro = 10^3 * ps' Nano+ps' Milli = 10^3 * ps' Micro+ps' Seconds = 10^3 * ps' Milli +ps' Minutes = 60 * ps' Seconds+ps' Hours = 60 * ps' Minutes+ps' Days = 24 * ps' Hours++-- | Helper function for show_time function+range :: Integer -> Range+range t = + if (t < 10^3) then Pico else+ if (t < 10^6) then Nano else+ if (t < 10^9) then Micro else+ if (t < 10^12) then Milli else+ if (t < 60*(10^12)) then Seconds else+ if (t < 60*60*(10^12)) then Minutes else+ if (t < 24*60*60*(10^12)) then Hours else Days
@@ -0,0 +1,95 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/TemplateTest.hs" #-}+-- | This file illustrates the most basic use of Template Haskell.++import Quipper++-- | A classical implementation of some boolean function.++example1 :: Bool -> Bool -> Bool+example1 a b = (a && b) || not a+++{-# LINE 9 "Quipper/Demos/TemplateTest.hs" #-}+$( decToCircMonad [d| example1 :: Bool -> Bool -> Bool+ example1 a b = (a && b) || not a+ + + |] ) +{-# LINE 10 "Quipper/Demos/TemplateTest.hs" #-}+-- $ The keyword \"build_circuit\" causes an equivalent quantum function+-- to be built automatically. It will have the following name and+-- type:+-- +-- > template_example1 :: Circ (Qubit -> Circ (Qubit -> Circ Qubit))+-- +-- The various nested 'Circ' applications are an artifact, and can and+-- should be removed using the 'unpack' operator:+-- +-- > (unpack template_example1) :: Qubit -> Qubit -> Circ Qubit++-- | This main function prints the circuit generated from 'example1'.+main1 :: IO ()+main1 =+ print_simple Preview (unpack template_example1)++-- | Here is some other boolean function. We do not use the+-- \"build_circuit\" keyword.+fake :: Bool -> Bool+fake b = not b++-- $ Suppose we want to use the function 'fake' as a subroutine+-- elsewhere:+{-++example2 :: Bool -> Bool -> Bool+example2 a b = fake (a && b) || not a++{-# LINE 36 "Quipper/Demos/TemplateTest.hs" #-}+$( decToCircMonad [d| example2 :: Bool -> Bool -> Bool+ example2 a b = fake (a && b) || not a+ + |] ) +{-# LINE 37 "Quipper/Demos/TemplateTest.hs" #-}+-}++-- | This will fail, because build_circuit does not know how to+-- translate the 'fake' function. +-- +-- We can fix this by manually providing a template. This is useful in+-- two situations:+-- +-- 1. To provide a template for a Haskell built-in function;+-- +-- 2. To provide a more efficient template for some function than the+-- one build_circuit can build automatically.+template_fake :: Circ (Qubit -> Circ Qubit)+template_fake = return f where+ f q = do+ qnot_at q+ return q++-- | Now that a template for 'fake' has been defined, the definition+-- of 'example2' works:++example2 :: Bool -> Bool -> Bool+example2 a b = fake (a && b) || not a++++{-# LINE 61 "Quipper/Demos/TemplateTest.hs" #-}+$( decToCircMonad [d| example2 :: Bool -> Bool -> Bool+ example2 a b = fake (a && b) || not a+ + + + |] ) +{-# LINE 62 "Quipper/Demos/TemplateTest.hs" #-}+-- | This main function prints the circuit generated from 'example2'. +main2 :: IO ()+main2 =+ print_simple Preview (unpack template_example2)++main = main2
@@ -0,0 +1,35 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Test.hs" #-}+import Quipper++circuit :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+circuit (a, b, c) = do+ qnot_at a `controlled` [b]+ qnot_at b `controlled` [c]+ hadamard c `controlled` [a,b]+ return (a, b, c)++hadamard2 :: (Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit)+hadamard2 (h, a, b) = do+ with_ancilla $ \c -> do+ qnot_at c `controlled` [a, b]+ hadamard h `controlled` [c]+ qnot_at c `controlled` [a, b]+ return (h, a, b)++example :: (Qubit, Qubit, Qubit, Qubit, Qubit) -> Circ (Qubit, Qubit, Qubit, Qubit, Qubit)+example (a, b, c, d, e) = do+ circuit (a, b, c)+ circuit (b, c, a)+ with_controls (d .==. 1 .&&. e .==. 0) $ do {+ circuit (a, b, c);+ circuit (b, c, a);+ }+ circuit (a, b, c)+ circuit (b, c, a)+ return (a, b, c, d, e)++main =+ print_simple Preview example
@@ -0,0 +1,83 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/Testing.hs" #-}+{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}++-- $+-- Generate some circuits for the slides in the PI presentation.++import Quipper++example_H3 :: Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example_H3 h a b c = do+ with_ancilla $ \d -> do+ with_ancilla $ \e -> do+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ hadamard_at h `controlled` e .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1++example_H3' :: Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example_H3' h a b c d e = do+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ hadamard_at h `controlled` e .==. 1+ qnot_at e `controlled` c .==. 1 .&&. d .==. 1+ qnot_at d `controlled` a .==. 1 .&&. b .==. 1++example :: Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example a b c d = do+ example_H3 a b c d+ qnot_at a `controlled` b .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at c `controlled` d .==. 1 .&&. a .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at a `controlled` b .==. 1+ example_H3 b c d a++example' :: Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Qubit -> Circ ()+example' a b c d anc1 anc2 = do+ example_H3' a b c d anc1 anc2+ qnot_at a `controlled` b .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at c `controlled` d .==. 1 .&&. a .==. 1+ qnot_at b `controlled` c .==. 1+ qnot_at a `controlled` b .==. 1+ example_H3' b c d a anc1 anc2+++main3 =+ print_generic Preview example qubit qubit qubit qubit++main =+ print_simple Preview example'++ec1 :: Qubit -> Circ [Qubit]+ec1 a = do+ b <- qinit False+ c <- qinit False+ qmultinot_at (b,c) `controlled` a .==. 1+ return [a,b,c]++corr :: [Qubit] -> Circ Qubit+corr [a,b,c] = do+ qmultinot_at (a,c) `controlled` b .==. 1+ (a',c') <- measure (a,c)+ qnot_at b `controlled` a' .==. 1 .&&. c' .==. 1+ cdiscard (a',c')+ return b++ec2 :: [Qubit] -> Circ [Qubit]+ec2 [a,b,c] = do+ [a1,a2,a3] <- ec1 a+ [b1,b2,b3] <- ec1 b+ [c1,c2,c3] <- ec1 c+ x1 <- corr [a1,b1,c1]+ x2 <- corr [a2,b2,c2]+ x3 <- corr [a3,b3,c3]+ return [x1,x2,x3]+++main4 = print_generic Preview ec2 [qubit, qubit, qubit]
@@ -0,0 +1,39 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Algorithms/BWT/Definitions.hs" #-}+-- | This module provides some convenient definitions for the Binary+-- Welded Tree algorithm implementation.++module Quipper.Algorithms.BWT.Definitions where++import Quipper++-- ======================================================================+-- * Some convenient gates++-- | Apply the binary /W/-gate to a pair of qubits. The W-gate+-- diagonalizes the SWAP operation.+wGate :: (Qubit, Qubit) -> Circ ()+wGate (a,b) = do+ gate_W a b+ return ()++-- | Apply the /inverse/ of the /W/-gate. Note: since the /W/-gate is+-- self-inverse, this is really the same as 'wGate'. However, we+-- define this as a separate function for clarity. +wGateInverse :: (Qubit, Qubit) -> Circ ()+wGateInverse = wGate++-- | Apply a doubly-controlled not gate to a triple of qubits (/a/,+-- /b/, /c/). Here the qubit /c/ is negated if /a/=1 and /b/=0.+toffoliGate :: (Qubit, Qubit, Qubit) -> Circ ()+toffoliGate (a, b, c) =+ qnot_at c `controlled` (a .==. 1 .&&. b .==. 0)++-- | @controlledExpGate(t, r, h):@+-- Apply the [exp −/iZt/] gate to the qubit /h/, provided that /r/=0. +controlledExpGate :: (Timestep, Qubit, Qubit) -> Circ ()+controlledExpGate (t, r, h) = do+ expZt t h `controlled` (r .==. 0)+ return ()
@@ -0,0 +1,40 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/TimeStep-binary.hs" #-}+import Quipper+import Quipper.Libraries.Qureg+import Quipper.Libraries.Decompose++import Quipper.Algorithms.BWT.Definitions++-- | Algorithm 3. @timestep (a, b, r, dt, m)@: Apply the+-- time step /dt/ to (/a/,/b/,/r/). Here /a/ and /b/ are /m/-qubit+-- registers while /r/ is a single qubit.+timestep :: (Qureg, Qureg, Qubit, Timestep, Int) -> Circ ()+timestep (a, b, r, dt, m) = do+ comment_with_label "ENTER: timestep" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ for 0 (m-1) 1 $ \i -> do+ wGate (a.!(i), b.!(i))+ endfor+ for 0 (m-1) 1 $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ controlledExpGate (dt, r, h)+ for (m-1) 0 (-1) $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ for (m-1) 0 (-1) $ \i -> do+ wGateInverse (a.!(i), b.!(i))+ endfor+ comment_with_label "EXIT: timestep" (a,b,r) ("a","b","r")+ return ()++main = print_generic Preview (decompose_generic Binary circuit) (nodeshape, nodeshape, qubit)+ where+ circuit (a, b, r) = timestep (a, b, r, dt, m)+ n = 4+ m = n+2+ dt = pi/180+ nodeshape = qureg_shape m
@@ -0,0 +1,39 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Algorithms/BWT/Definitions.hs" #-}+-- | This module provides some convenient definitions for the Binary+-- Welded Tree algorithm implementation.++module Quipper.Algorithms.BWT.Definitions where++import Quipper++-- ======================================================================+-- * Some convenient gates++-- | Apply the binary /W/-gate to a pair of qubits. The W-gate+-- diagonalizes the SWAP operation.+wGate :: (Qubit, Qubit) -> Circ ()+wGate (a,b) = do+ gate_W a b+ return ()++-- | Apply the /inverse/ of the /W/-gate. Note: since the /W/-gate is+-- self-inverse, this is really the same as 'wGate'. However, we+-- define this as a separate function for clarity. +wGateInverse :: (Qubit, Qubit) -> Circ ()+wGateInverse = wGate++-- | Apply a doubly-controlled not gate to a triple of qubits (/a/,+-- /b/, /c/). Here the qubit /c/ is negated if /a/=1 and /b/=0.+toffoliGate :: (Qubit, Qubit, Qubit) -> Circ ()+toffoliGate (a, b, c) =+ qnot_at c `controlled` (a .==. 1 .&&. b .==. 0)++-- | @controlledExpGate(t, r, h):@+-- Apply the [exp −/iZt/] gate to the qubit /h/, provided that /r/=0. +controlledExpGate :: (Timestep, Qubit, Qubit) -> Circ ()+controlledExpGate (t, r, h) = do+ expZt t h `controlled` (r .==. 0)+ return ()
@@ -0,0 +1,38 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/TimeStep.hs" #-}+import Quipper+import Quipper.Libraries.Qureg+import Quipper.Algorithms.BWT.Definitions++-- | Algorithm 3. @timestep (a, b, r, dt, m)@: Apply the+-- time step /dt/ to (/a/,/b/,/r/). Here /a/ and /b/ are /m/-qubit+-- registers while /r/ is a single qubit.+timestep :: (Qureg, Qureg, Qubit, Timestep, Int) -> Circ ()+timestep (a, b, r, dt, m) = do+ comment_with_label "ENTER: timestep" (a,b,r) ("a","b","r")+ with_ancilla $ \h -> do+ for 0 (m-1) 1 $ \i -> do+ wGate (a.!(i), b.!(i))+ endfor+ for 0 (m-1) 1 $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ controlledExpGate (dt, r, h)+ for (m-1) 0 (-1) $ \i -> do+ toffoliGate (a.!(i), b.!(i), h)+ endfor+ for (m-1) 0 (-1) $ \i -> do+ wGateInverse (a.!(i), b.!(i))+ endfor+ comment_with_label "EXIT: timestep" (a,b,r) ("a","b","r")+ return ()++main = print_generic Preview circuit (nodeshape, nodeshape, qubit)+ where+ circuit (a, b, r) = timestep (a, b, r, dt, m)+ n = 4+ m = n+2+ dt = pi/180+ nodeshape = qureg_shape m
@@ -0,0 +1,27 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/TransformerExample.hs" #-}+import Quipper+ +mytransformer :: Transformer Circ Qubit Bit+mytransformer (T_QGate "swap" 2 0 _ ncf f) = f $+ \[q0, q1] [] ctrls -> do+ without_controls_if ncf $ do+ with_controls ctrls $ do+ qnot_at q0 `controlled` q1+ qnot_at q1 `controlled` q0+ qnot_at q0 `controlled` q1+ return ([q0, q1], [], ctrls)+mytransformer g = identity_transformer g++mycirc a b c d = do+ swap_at a b+ hadamard_at b+ swap_at b c `controlled` [a, d]+ hadamard_at c+ swap_at c d++mycirc2 = transform_generic mytransformer mycirc++main = print_simple Preview mycirc2
@@ -0,0 +1,44 @@+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies #-}+{-# LINE 1 "Quipper/Demos/WithComputed.hs" #-}+import Quipper++crazy :: (QData a, QCData b) => (a -> Circ b) -> (a -> Circ (a,b))+crazy f a = do+ mapUnary hadamard a+ y <- with_computed (f a) $ \b -> do+ b' <- qc_copy b+ return (a,b')+ return y++circuit :: [Qubit] -> Circ ([Qubit], [Qubit])+circuit qs = do+ y <- with_computed values $ \values -> do+ qc_copy values+ return (qs, y)+ + where+ values = do+ mapUnary hadamard qs+ a <- qinit True+ b <- qinit False+ qnot_at a `controlled` qs+ qnot_at b `controlled` qs .==. [0,0..]+ c <- qinit False+ qnot_at c `controlled` [a,b]+ qnot_at b `controlled` qs .==. [0,0..]+ qnot_at a `controlled` qs+ qterm False b + qterm True a+ return (c:qs)++circuit2 :: [Qubit] -> Circ ([Qubit], ([Qubit], [Qubit]))+circuit2 = crazy circuit++circuit3 :: [Qubit] -> Circ ([Qubit], ([Qubit], ([Qubit], [Qubit])))+circuit3 = crazy circuit2++circuit4 = crazy circuit3++main = print_generic Preview circuit4 (replicate 5 qubit)
binary file changed (absent → 3311 bytes)
binary file changed (absent → 1496 bytes)
binary file changed (absent → 1572 bytes)
binary file changed (absent → 3957 bytes)
binary file changed (absent → 1738 bytes)
binary file changed (absent → 3363 bytes)
binary file changed (absent → 1963 bytes)
binary file changed (absent → 1561 bytes)
binary file changed (absent → 1804 bytes)
binary file changed (absent → 2532 bytes)
binary file changed (absent → 1360 bytes)
binary file changed (absent → 4858 bytes)
binary file changed (absent → 8371 bytes)
binary file changed (absent → 887 bytes)
binary file changed (absent → 5013 bytes)
binary file changed (absent → 5628 bytes)
binary file changed (absent → 1304 bytes)
binary file changed (absent → 7265 bytes)
binary file changed (absent → 13792 bytes)
binary file changed (absent → 1544 bytes)
binary file changed (absent → 2929 bytes)
binary file changed (absent → 7580 bytes)
binary file changed (absent → 3038 bytes)
binary file changed (absent → 3642 bytes)
binary file changed (absent → 2484 bytes)
binary file changed (absent → 1151 bytes)
binary file changed (absent → 1433 bytes)
binary file changed (absent → 1940 bytes)
binary file changed (absent → 2085 bytes)
binary file changed (absent → 1308 bytes)
binary file changed (absent → 4450 bytes)
binary file changed (absent → 1716 bytes)
binary file changed (absent → 4991 bytes)
binary file changed (absent → 1878 bytes)
binary file changed (absent → 963 bytes)
binary file changed (absent → 1551 bytes)
binary file changed (absent → 14953 bytes)
binary file changed (absent → 2436 bytes)
binary file changed (absent → 2433 bytes)
binary file changed (absent → 3058 bytes)
binary file changed (absent → 4290 bytes)
binary file changed (absent → 4864 bytes)
binary file changed (absent → 3545 bytes)
binary file changed (absent → 1268 bytes)
binary file changed (absent → 2669 bytes)
binary file changed (absent → 2247 bytes)
binary file changed (absent → 1738 bytes)
binary file changed (absent → 1002 bytes)
binary file changed (absent → 3523 bytes)
binary file changed (absent → 2403 bytes)
binary file changed (absent → 12639 bytes)
binary file changed (absent → 19618 bytes)
binary file changed (absent → 6734 bytes)
binary file changed (absent → 1318 bytes)
binary file changed (absent → 4358 bytes)
binary file changed (absent → 5276 bytes)
binary file changed (absent → 1167 bytes)
binary file changed (absent → 1152 bytes)
binary file changed (absent → 913 bytes)
binary file changed (absent → 1664 bytes)
binary file changed (absent → 2436 bytes)
binary file changed (absent → 3399 bytes)
binary file changed (absent → 3310 bytes)
binary file changed (absent → 3209 bytes)
binary file changed (absent → 7982 bytes)
binary file changed (absent → 1768 bytes)
binary file changed (absent → 8963 bytes)
binary file changed (absent → 4107 bytes)
binary file changed (absent → 3598 bytes)
binary file changed (absent → 5029 bytes)
binary file changed (absent → 1052 bytes)
@@ -0,0 +1,438 @@+-- The name of the package.+name: quipper-demos++-- The package version. See the Haskell package versioning policy (PVP) +-- for standards guiding when and how versions should be incremented.+-- http://www.haskell.org/haskellwiki/Package_versioning_policy+-- PVP summary: +-+------- breaking API changes+-- | | +----- non-breaking API additions+-- | | | +--- code changes with no API change+version: 0.9.0.0++-- A short (one-line) description of the package.+synopsis: Miscellaneous code snippets that illustrate various Quipper features.++-- A longer description of the package.+description: ++ This package provides some code snippets that illustrate various+ Quipper features.+ +-- URL for the project homepage or repository.+homepage: http://www.mathstat.dal.ca/~selinger/quipper/++-- The license under which the package is released.+license: BSD3++-- The file containing the license text.+license-file: COPYRIGHT++-- The package author(s).+author: Alexander S. Green, Peter LeFanu Lumsdaine,+ Neil J. Ross, Peter Selinger, Benoit Valiron++-- An email address to which users can send suggestions, bug reports, and +-- patches.+maintainer: selinger@mathstat.dal.ca++-- A copyright notice.+copyright: Copyright (c) 2011-2019. All rights reserved.++-- A classification category for future use by the package catalogue+-- Hackage. These categories have not yet been specified, but the+-- upper levels of the module hierarchy make a good start.+category: Quipper++-- The type of build used by this package.+build-type: Custom++-- Constraint on the version of Cabal needed to build this package.+cabal-version: >= 1.8++-- A list of additional files to be included in source distributions+-- built with setup sdist.+extra-source-files: images/*.png ChangeLog++-- We must export a library, even if it is empty, or else+-- meta-packages (such as quipper-all) that depend on this package+-- will fail.+library+ exposed-modules:+ +executable And_gate+ main-is: Quipper/Demos/And_gate.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable And_list+ main-is: Quipper/Demos/And_list.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable And_rev+ main-is: Quipper/Demos/And_rev.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Arith+ main-is: Quipper/Demos/Arith.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable BoxExample+ main-is: Quipper/Demos/BoxExample.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Box+ main-is: Quipper/Demos/Box.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Classical+ main-is: Quipper/Demos/Classical.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Comments+ main-is: Quipper/Demos/Comments.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable CountAccess+ main-is: Quipper/Demos/CountAccess.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Decompose_test+ main-is: Quipper/Demos/Decompose_test.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable DynamicLifting+ main-is: Quipper/Demos/DynamicLifting.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable ErrorCircuit+ main-is: Quipper/Demos/ErrorCircuit.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Example1+ main-is: Quipper/Demos/Example1.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Example2+ main-is: Quipper/Demos/Example2.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Example3+ main-is: Quipper/Demos/Example3.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Example4+ main-is: Quipper/Demos/Example4.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Example+ main-is: Quipper/Demos/Example.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable GPhase+ main-is: Quipper/Demos/GPhase.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable HelloWorld+ main-is: Quipper/Demos/HelloWorld.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Infinite+ main-is: Quipper/Demos/Infinite.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries++executable MultiControlledNot+ main-is: Quipper/Demos/MultiControlledNot.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable NamedGate+ main-is: Quipper/Demos/NamedGate.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable NBox+ main-is: Quipper/Demos/NBox.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable NoControl+ main-is: Quipper/Demos/NoControl.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable OptimTest+ main-is: Quipper/Demos/OptimTest.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable ParseNodeRoot+ main-is: Quipper/Demos/ParseNodeRoot.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable PhaseTest+ main-is: Quipper/Demos/PhaseTest.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable QEC+ main-is: Quipper/Demos/QEC.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable QFTAdder+ main-is: Quipper/Demos/QFTAdder.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable QFT+ main-is: Quipper/Demos/QFT.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable QRAM+ main-is: Quipper/Demos/QRAM.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable QuantumIfTest+ main-is: Quipper/Demos/QuantumIfTest.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Reverse+ main-is: Quipper/Demos/Reverse.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable SimpleOracleSimulation+ main-is: Quipper/Demos/SimpleOracleSimulation.hs+ build-depends:+ base >= 4.5 && < 5,+ containers >= 0.5.2.1,+ quipper-utils,+ quipper-language,+ quipper-libraries+ other-modules:+ Quipper.Algorithms.BWT.Definitions+ Quipper.Algorithms.BWT.BWT+ Quipper.Algorithms.BWT.Alternative+ +executable SimulationTest+ main-is: Quipper/Demos/SimulationTest.hs+ build-depends:+ base >= 4.5 && < 5,+ random >= 1.0.1.1,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable SynthesisTest+ main-is: Quipper/Demos/SynthesisTest.hs+ build-depends:+ base >= 4.5 && < 5,+ random >= 1.0.1.1,+ newsynth >= 0.3.0.1,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable TeleportGeneric+ main-is: Quipper/Demos/TeleportGeneric.hs+ build-depends:+ base >= 4.5 && < 5,+ random >= 1.0.1.1,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Teleport+ main-is: Quipper/Demos/Teleport.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable TemplateTest+ main-is: Quipper/Demos/TemplateTest.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Test+ main-is: Quipper/Demos/Test.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable Testing+ main-is: Quipper/Demos/Testing.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable TimeStep-binary+ main-is: Quipper/Demos/TimeStep-binary.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ other-modules:+ Quipper.Algorithms.BWT.Definitions+ +executable TimeStep+ main-is: Quipper/Demos/TimeStep.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ other-modules:+ Quipper.Algorithms.BWT.Definitions+ +executable TransformerExample+ main-is: Quipper/Demos/TransformerExample.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries+ +executable WithComputed+ main-is: Quipper/Demos/WithComputed.hs+ build-depends:+ base >= 4.5 && < 5,+ quipper-utils,+ quipper-language,+ quipper-libraries++custom-setup+ setup-depends: base >= 4.5,+ Cabal >= 1.24,+ quipper-cabal >= 0.9.0.0