Swap Networks#
Functionality for moving data between registers (swapping).
from qualtran import Bloq, CompositeBloq, BloqBuilder, Signature, Register
from qualtran import QBit, QInt, QUInt, QAny
from qualtran.drawing import show_bloq, show_call_graph, show_counts_sigma
from typing import *
import numpy as np
import sympy
import cirq
CSwapApprox
#
Approximately implements a multi-target controlled swap unitary using only \(4n\) T-gates.
Implements \(\mathrm{CSWAP}_n = |0 \rangle\langle 0| I + |1 \rangle\langle 1| \mathrm{SWAP}_n\) such that the output state is correct up to a relative phase factor of +1/-1 in the standard basis.
This is useful when the incorrect phase can be absorbed in a garbage state of an algorithm and thus ignored. See the reference for more details.
Parameters#
bitsize
: The bitsize of the two registers being swapped.
Registers#
ctrl
: the control bitx
: the first registery
: the second register
References#
Trading T-gates for dirty qubits in state preparation and unitary synthesis. Low et al. 2018. See Appendix B.2.c.
from qualtran.bloqs.swap_network import CSwapApprox
Example Instances#
# A symbolic version. The bitsize is the symbol 'n'.
from sympy import sympify
approx_cswap_symb = CSwapApprox(bitsize=sympify('n'))
# A small version on four bits.
approx_cswap_small = CSwapApprox(bitsize=4)
# A large version that swaps 64-bit registers.
approx_cswap_large = CSwapApprox(bitsize=64)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([approx_cswap_symb, approx_cswap_small, approx_cswap_large],
['`approx_cswap_symb`', '`approx_cswap_small`', '`approx_cswap_large`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
approx_cswap_symb_g, approx_cswap_symb_sigma = approx_cswap_symb.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(approx_cswap_symb_g)
show_counts_sigma(approx_cswap_symb_sigma)
Counts totals:
ArbitraryClifford(n=1)
: $\displaystyle 16 n$ArbitraryClifford(n=2)
: $\displaystyle 6 n - 1$T
: $\displaystyle 4 n$
SwapWithZero
#
Swaps \(|\Psi_0\rangle\) with \(|\Psi_x\rangle\) if selection register stores index x
.
Implements the unitary
Also supports the multidimensional version where \(|x\rangle\) can be an n-dimensional index of the form \(|x_1\rangle|x_2\rangle \dots |x_n\rangle\)
References#
Trading T-gates for dirty qubits in state preparation and unitary synthesis. Low, Kliuchnikov, Schaeffer. 2018.
from qualtran.bloqs.swap_network import SwapWithZero
Example Instances#
swz = SwapWithZero(selection_bitsizes=8, target_bitsize=32, n_target_registers=4)
# A small version on four bits.
swz_small = SwapWithZero(selection_bitsizes=3, target_bitsize=2, n_target_registers=2)
swz_multi_dimensional = SwapWithZero(
selection_bitsizes=(4, 3), target_bitsize=2, n_target_registers=(15, 5)
)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([swz, swz_small, swz_multi_dimensional],
['`swz`', '`swz_small`', '`swz_multi_dimensional`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
swz_g, swz_sigma = swz.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(swz_g)
show_counts_sigma(swz_sigma)
Counts totals:
CSwapApprox
: 3
MultiplexedCSwap
#
Swaps the \(l\)-th register into an ancilla using unary iteration.
Applies the unitary which performs
The toffoli cost should be \(L n_b + L - 2 + n_c\), where \(L\) is the iteration length, \(n_b\) is the bitsize of the registers to swap, and \(n_c\) is the number of controls.
Parameters#
selection_regs
: Indexingselect
signature of type Tuple[Register
, …]. It also contains information about the iteration length of each selection register.target_bitsize
: The size of the registers we want to swap.control_regs
: Control registers for constructing a controlled version of the gate.
Registers#
control_registers
: Control registersselection_regs
: Indexingselect
signature of type Tuple[Register
, …]. It also contains information about the iteration length of each selection register.target_registers
: Target registers to swap. We swap FROM registers labelled xi
, where i is an integer and TO a single register called y
References#
Fault-Tolerant Quantum Simulations of Chemistry in First Quantization. page 20 paragraph 2.
from qualtran.bloqs.swap_network import MultiplexedCSwap
Example Instances#
from qualtran import BQUInt
selection_bitsize = 3
iteration_length = 5
target_bitsize = 2
multiplexed_cswap = MultiplexedCSwap(
Register('selection', BQUInt(selection_bitsize, iteration_length)),
target_bitsize=target_bitsize,
)
Graphical Signature#
from qualtran.drawing import show_bloqs
show_bloqs([multiplexed_cswap],
['`multiplexed_cswap`'])
Call Graph#
from qualtran.resource_counting.generalizers import ignore_split_join
multiplexed_cswap_g, multiplexed_cswap_sigma = multiplexed_cswap.call_graph(max_depth=1, generalizer=ignore_split_join)
show_call_graph(multiplexed_cswap_g)
show_counts_sigma(multiplexed_cswap_sigma)
Counts totals:
And
: 3And†
: 3CNOT
: 3CSwap
: 5XGate
: 2
swz_multi_dimensional = SwapWithZero(
selection_bitsizes=(2, 2), target_bitsize=2, n_target_registers=(3, 4)
)
# A small version on four bits.
selection = sympy.symbols("p q r")
target_bitsize = sympy.Symbol("b")
n_target_registers = sympy.symbols("P Q R")
swz_multi_symbolic = SwapWithZero(
selection_bitsizes=selection,
target_bitsize=target_bitsize,
n_target_registers=n_target_registers,
)