This section introduces the unitary operators needed by the Shor algorithm presented in section 3.3.
(3.12) |
qufunct flip(qureg q) { // pseudo classic op to swap bit order int i; // declare loop counter for i=0 to #q/2-1 { // swap 2 symmetric bits Swap(q[i],q[#q-i-1]); } } |
(3.13) |
qufunct cxor(quconst a,qureg b,quconst enable) { int i; for i=0 to #a-1 { CNot(b[i],a[i] & enable); } } |
Comparing two classical binary numbers and can be simply achieved by comparing form the highest to the lowest bits and returning at the first mismatch.
for i=n-1 to 0 { // check whether b<a if bit(b,i)<bit(a,i) { return true; } } return false; |
One possibility is to emulate an early return from the loop by using conditional operators (see section 1.3.5): For each bit comparison, we use an enable bit which is set to 1 if the bits are equal (and the loop has to continue) or to 0 if the result is decided and further comparisons should be disabled.
To compare an qubit register to a classical integer , we have to use an junk register to store the enable bits. The main loop of the quantum comparison then runs a follows.
for i=#b-2 to 1 step -1 { // continue for lower bits if bit(a,i) { // set new junk bit if undecided CNot(j[i-1],j[i] & b[i]); Not(b[i]); // honour last junk bit and CNot(flag,j[i] & b[i]); // set result flag if a[i]>b[i] } else { Not(b[i]); CNot(j[i-1],j[i] & b[i]); } Not(b[i]); // restore b[i] again } |
A multiplexed adder adds one of two classical bits and to a qubit , depending on the content of a selection qubit . The target register consists of a carry-in and a carry-out qubit, to allow cascading. The truth table for the operation is:
|
|
qufunct muxadd(int a0,int a1,qureg sel,quconst b,quvoid sum,quconst e) { int i; for i=0 to #b-2 { // fulladd first #b-1 bits muxaddbit(bit(a0,i),bit(a1,i),sel,b[i],sum[i:i+1],e); } // half add last bit muxaddbit(bit(a0,#b-1),bit(a1,#b-1),sel,b[#b-1],sum[#b-1],e); } |
Many number theoretic algorithms describe calculations in the remainder class . On example for a quantum algorithm using modular arithmetic, is Shor's method of polynomial time quantum factoring (see section 3.3).[11].
For a more detailed discussion of unitary operators for modular arithmetic, please refer to [13].
The addition modulo of a classic integer and a quantum register can result in either or , depending on the particular base-vector .
While for the operation is revertible, this is not
the case for , so, if doesn't happen
to be a power of , besides the target resister
for the sum, we need an additional flag-qubit
to allow for a quantum function addn
which is both, unitary and invariant to :
(3.14) |
qufunct addn(int a,int n,quconst b,quvoid flag,quvoid sum,quconst e) { qureg s=sum[0\#b-1]; qureg f=sum[#b-1]; qureg bb=b; // "abuse" sum and b as scratch lt(n-a,bb,f,s); // for the less-than operator CNot(flag,f & e); // save result of comparison !lt(n-a,bb,f,s); // restore sum and b muxadd(2^#b+a-n,a,flag,b,sum,e); // add either a or a-n } |
Since
is a quantum function for
modular subtraction and thus implements the inverse function
to
,
we can construct an overwriting version oaddn
of modular addition, by using the method introduced
in section 1.3.4.3:
(3.15) |
(3.16) |
qufunct oaddn(int a,int n,qureg sum,quconst e) { qureg j[#sum]; qureg f[1]; addn(a,n,sum,f,j,e); // junk -> a+b mod n Swap(sum,j); // swap junk and sum CNot(f,e); // toggle flag !addn(n-a,n,sum,f,j,e); // uncompute b to zero } |
Modular multiplication is merely a composition of conditional
additions for each qubit of since
(3.17) |
qufunct muln(int a,int n,quconst b,qureg prod,quconst e) { int i; for i=0 to #prod-1 { if bit(a,i) { CNot(prod[i],b[0] & e); } } for i=1 to #b-1 { oaddn(2^i*a mod n,n,prod,b[i] & e); } } |
By using two conditional XOR gates (see section 3.2.1.1) for swapping the registers3.2we can implement a conditional
qufunct omuln(int a,int n,qureg b,quconst e) { qureg j[#b]; muln(a,n,b,j,e); !muln(invmod(a,n),n,j,b,e); cxor(j,b,e); cxor(b,j,e); } |
As with muln, we can construct modular exponentiation
by conditionally applying omuln with the qubits
of the exponents as enable string, according to
(3.18) |
qufunct expn(int a,int n,quconst b,quvoid ex) { int i; Not(ex[0]); // start with 1 for i=0 to #b-1 { omuln(powmod(a,2^i,n),n,ex,b[i]); // ex -> ex*a^2^i mod n } } |
For a dimensional vector
, the discrete
Fourier transform is defined as
(3.19) |
As suggested by Coppersmith [7],
the same principle could adapted be to quantum computers
by using a combination of Hadamard transformations and
conditional phase gates (indices indicate the
qubits operated on):
(3.20) |
The base-vectors of the transformed state are given in reverse bit order, so the get the actual , the bits have to be flipped.
operator dft(qureg q) { // main operator const n=#q; // set n to length of input int i; int j; // declare loop counters for i=0 to n-1 { for j=0 to i-1 { // apply conditional phase gates CPhase(2*pi/2^(i-j+1),q[n-i-1] & q[n-j-1]); } Mix(q[n-i-1]); // qubit rotation } flip(q); // swap bit order of the output } |