These code samples were written by Eric Johnston, Nic Harrigan, and Mercedes Gimeno-Segovia.
from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, execute, Aer, IBMQ, BasicAer
import math
%matplotlib inline
## Example 5-1: Increment and Decrement
## Note that this looks different from the gates in the book, because
## we're building the operations from Toffoli gates
# Set up the program
a = QuantumRegister(4, name='a')
scratch = QuantumRegister(1, name='scratch')
qc = QuantumCircuit(a, scratch)
def main():
## initialization
qc.x(a[0])
qc.h(a[2])
qc.rz(math.radians(45), a[2])
qc.barrier()
## Increment
add_int(a, 1)
qc.barrier()
## Decrement
add_int(a, -1)
###############################################
## Some utility functions
def add_int(qdest, rhs):
reverse_to_subtract = False
if rhs == 0:
return
elif rhs < 0:
rhs = -rhs
reverse_to_subtract = True
ops = []
add_val = int(rhs)
condition_mask = (1 << len(qdest)) - 1
add_val_mask = 1
while add_val_mask <= add_val:
cmask = condition_mask & ~(add_val_mask - 1)
if add_val_mask & add_val:
add_shift_mask = 1 << (len(qdest) - 1)
while add_shift_mask >= add_val_mask:
cmask &= ~add_shift_mask
ops.append((add_shift_mask, cmask))
add_shift_mask >>= 1
condition_mask &= ~add_val_mask
add_val_mask <<= 1
if reverse_to_subtract:
ops.reverse()
for inst in ops:
op_qubits = []
mask = 1
for i in range(len(qdest)):
if inst[1] & (1 << i):
op_qubits.append(qdest[i])
for i in range(len(qdest)):
if inst[0] & (1 << i):
op_qubits.append(qdest[i])
multi_cx(op_qubits)
def multi_cz(qubits):
## This will perform a CCCCCZ on as many qubits as we want,
## as long as we have enough scratch qubits
multi_cx(qubits, do_cz=True)
def multi_cx(qubits, do_cz=False):
## This will perform a CCCCCX with as many conditions as we want,
## as long as we have enough scratch qubits
## The last qubit in the list is the target.
target = qubits[-1]
conds = qubits[:-1]
scratch_index = 0
ops = []
while len(conds) > 2:
new_conds = []
for i in range(len(conds)//2):
ops.append((conds[i * 2], conds[i * 2 + 1], scratch[scratch_index]))
new_conds.append(scratch[scratch_index])
scratch_index += 1
if len(conds) & 1:
new_conds.append(conds[-1])
conds = new_conds
for op in ops:
qc.ccx(op[0], op[1], op[2])
if do_cz:
qc.h(target)
if len(conds) == 0:
qc.x(target)
elif len(conds) == 1:
qc.cx(conds[0], target)
else:
qc.ccx(conds[0], conds[1], target)
if do_cz:
qc.h(target)
ops.reverse()
for op in ops:
qc.ccx(op[0], op[1], op[2])
main()
## That's the program. Everything below runs and draws it.
backend = BasicAer.get_backend('statevector_simulator')
job = execute(qc, backend)
result = job.result()
outputstate = result.get_statevector(qc, decimals=3)
for i,amp in enumerate(outputstate):
if abs(amp) > 0.000001:
print('|{}> {}'.format(i, amp))
qc.draw() # draw the circuit
|1> (0.707+0j) |5> (0.5+0.5j)
## Example 5-2: Adding Two Quantum Integers
## Note that this looks different from the gates in the book, because
## we're building the operations from Toffoli gates
# Set up the program
a = QuantumRegister(4, name='a')
b = QuantumRegister(2, name='b')
scratch = QuantumRegister(2, name='scratch')
qc = QuantumCircuit(a, b, scratch)
def main():
## initialization
qc.x(a[0])
qc.h(a[2])
qc.rz(math.radians(45), a[2])
qc.x(b[0])
qc.h(b[1])
qc.rz(math.radians(90), b[1])
qc.barrier()
## Increment
add_qint(a, b)
###############################################
## Some utility functions
def add_qint(qdest, rhs):
for bit in range(len(rhs)):
add_int(qdest, 1 << bit, [rhs[bit]])
def add_int(qdest, rhs, condition_qubits=None):
if condition_qubits is None:
condition_qubits = []
reverse_to_subtract = False
if rhs == 0:
return
elif rhs < 0:
rhs = -rhs
reverse_to_subtract = True
ops = []
add_val = int(rhs)
condition_mask = (1 << len(qdest)) - 1
add_val_mask = 1
while add_val_mask <= add_val:
cmask = condition_mask & ~(add_val_mask - 1)
if add_val_mask & add_val:
add_shift_mask = 1 << (len(qdest) - 1)
while add_shift_mask >= add_val_mask:
cmask &= ~add_shift_mask
ops.append((add_shift_mask, cmask))
add_shift_mask >>= 1
condition_mask &= ~add_val_mask
add_val_mask <<= 1
if reverse_to_subtract:
ops.reverse()
for inst in ops:
op_qubits = [x for x in condition_qubits]
mask = 1
for i in range(len(qdest)):
if inst[1] & (1 << i):
op_qubits.append(qdest[i])
for i in range(len(qdest)):
if inst[0] & (1 << i):
op_qubits.append(qdest[i])
multi_cx(op_qubits)
def multi_cz(qubits):
## This will perform a CCCCCZ on as many qubits as we want,
## as long as we have enough scratch qubits
multi_cx(qubits, do_cz=True)
def multi_cx(qubits, do_cz=False):
## This will perform a CCCCCX with as many conditions as we want,
## as long as we have enough scratch qubits
## The last qubit in the list is the target.
target = qubits[-1]
conds = qubits[:-1]
scratch_index = 0
ops = []
while len(conds) > 2:
new_conds = []
for i in range(len(conds)//2):
ops.append((conds[i * 2], conds[i * 2 + 1], scratch[scratch_index]))
new_conds.append(scratch[scratch_index])
scratch_index += 1
if len(conds) & 1:
new_conds.append(conds[-1])
conds = new_conds
for op in ops:
qc.ccx(op[0], op[1], op[2])
if do_cz:
qc.h(target)
if len(conds) == 0:
qc.x(target)
elif len(conds) == 1:
qc.cx(conds[0], target)
else:
qc.ccx(conds[0], conds[1], target)
if do_cz:
qc.h(target)
ops.reverse()
for op in ops:
qc.ccx(op[0], op[1], op[2])
main()
## That's the program. Everything below runs and draws it.
backend = BasicAer.get_backend('statevector_simulator')
job = execute(qc, backend)
result = job.result()
outputstate = result.get_statevector(qc, decimals=3)
for i,amp in enumerate(outputstate):
if abs(amp) > 0.000001:
print('|{}> {}'.format(i, amp))
qc.draw() # draw the circuit
|18> (0.5+0j) |22> (0.354+0.354j) |52> 0.5j |56> (-0.354+0.354j)
## Example 5-3: Add squared value of one qint to another
## Note that this looks different from the gates in the book, because
## we're building the operations from Toffoli gates
# Set up the program
a = QuantumRegister(4, name='a')
b = QuantumRegister(2, name='b')
scratch = QuantumRegister(2, name='scratch')
qc = QuantumCircuit(a, b, scratch)
def main():
## initialization
qc.x(a[0])
qc.h(a[2])
qc.rz(math.radians(45), a[2])
qc.x(b[0])
qc.h(b[1])
qc.rz(math.radians(90), b[1])
qc.barrier()
## Increment
add_squared_qint(a, b)
###############################################
## Some utility functions
def add_squared_qint(qdest, rhs, condition_qubits=None):
if condition_qubits is None:
condition_qubits = []
for bit in range(len(rhs)):
slideMask = list(set(condition_qubits + [rhs[bit]]))
add_qint(qdest, rhs, slideMask, bit);
def add_qint(qdest, rhs, condition_qubits=None, shiftRHS=0):
if condition_qubits is None:
condition_qubits = []
for bit in range(len(rhs)):
add_int(qdest, 1 << bit, list(set([rhs[bit]] + condition_qubits)), shiftRHS)
def add_int(qdest, rhs, condition_qubits=None, shiftRHS=0):
if condition_qubits is None:
condition_qubits = []
reverse_to_subtract = False
if rhs == 0:
return
elif rhs < 0:
rhs = -rhs
reverse_to_subtract = True
rhs <<= shiftRHS
ops = []
add_val = int(rhs)
condition_mask = (1 << len(qdest)) - 1
add_val_mask = 1
while add_val_mask <= add_val:
cmask = condition_mask & ~(add_val_mask - 1)
if add_val_mask & add_val:
add_shift_mask = 1 << (len(qdest) - 1)
while add_shift_mask >= add_val_mask:
cmask &= ~add_shift_mask
ops.append((add_shift_mask, cmask))
add_shift_mask >>= 1
condition_mask &= ~add_val_mask
add_val_mask <<= 1
if reverse_to_subtract:
ops.reverse()
for inst in ops:
op_qubits = [x for x in condition_qubits]
mask = 1
for i in range(len(qdest)):
if inst[1] & (1 << i):
op_qubits.append(qdest[i])
for i in range(len(qdest)):
if inst[0] & (1 << i):
op_qubits.append(qdest[i])
multi_cx(op_qubits)
def multi_cz(qubits):
## This will perform a CCCCCZ on as many qubits as we want,
## as long as we have enough scratch qubits
multi_cx(qubits, do_cz=True)
def multi_cx(qubits, do_cz=False):
## This will perform a CCCCCX with as many conditions as we want,
## as long as we have enough scratch qubits
## The last qubit in the list is the target.
target = qubits[-1]
conds = qubits[:-1]
scratch_index = 0
ops = []
while len(conds) > 2:
new_conds = []
for i in range(len(conds)//2):
ops.append((conds[i * 2], conds[i * 2 + 1], scratch[scratch_index]))
new_conds.append(scratch[scratch_index])
scratch_index += 1
if len(conds) & 1:
new_conds.append(conds[-1])
conds = new_conds
for op in ops:
qc.ccx(op[0], op[1], op[2])
if do_cz:
qc.h(target)
if len(conds) == 0:
qc.x(target)
elif len(conds) == 1:
qc.cx(conds[0], target)
else:
qc.ccx(conds[0], conds[1], target)
if do_cz:
qc.h(target)
ops.reverse()
for op in ops:
qc.ccx(op[0], op[1], op[2])
main()
## That's the program. Everything below runs and draws it.
backend = BasicAer.get_backend('statevector_simulator')
job = execute(qc, backend)
result = job.result()
outputstate = result.get_statevector(qc, decimals=3)
for i,amp in enumerate(outputstate):
if abs(amp) > 0.000001:
print('|{}> {}'.format(i, amp))
qc.draw() # draw the circuit
|18> (0.5-0j) |22> (0.354+0.354j) |58> 0.5j |62> (-0.354+0.354j)
## Example 5-4: Quantum conditional execution
## Note that this looks different from the gates in the book, because
## we're building the operations from Toffoli gates
# Set up the program
a = QuantumRegister(3, name='a')
b = QuantumRegister(3, name='b')
scratch = QuantumRegister(1, name='scratch')
qc = QuantumCircuit(a, b, scratch)
def main():
## initialization
qc.x(a[0])
qc.h(a[2])
qc.x(b[0])
qc.h(b[1])
qc.rz(math.radians(90), b[1])
qc.barrier()
## Increment
add_int(a, -3)
qc.barrier()
add_int(b, 1, [a[2]])
qc.barrier()
add_int(a, 3)
###############################################
## Some utility functions
def add_squared_qint(qdest, rhs, condition_qubits=None):
if condition_qubits is None:
condition_qubits = []
for bit in range(len(rhs)):
slideMask = list(set(condition_qubits + [rhs[bit]]))
add_qint(qdest, rhs, slideMask, bit);
def add_qint(qdest, rhs, condition_qubits=None, shiftRHS=0):
if condition_qubits is None:
condition_qubits = []
for bit in range(len(rhs)):
add_int(qdest, 1 << bit, list(set([rhs[bit]] + condition_qubits)), shiftRHS)
def add_int(qdest, rhs, condition_qubits=None, shiftRHS=0):
if condition_qubits is None:
condition_qubits = []
reverse_to_subtract = False
if rhs == 0:
return
elif rhs < 0:
rhs = -rhs
reverse_to_subtract = True
rhs <<= shiftRHS
ops = []
add_val = int(rhs)
condition_mask = (1 << len(qdest)) - 1
add_val_mask = 1
while add_val_mask <= add_val:
cmask = condition_mask & ~(add_val_mask - 1)
if add_val_mask & add_val:
add_shift_mask = 1 << (len(qdest) - 1)
while add_shift_mask >= add_val_mask:
cmask &= ~add_shift_mask
ops.append((add_shift_mask, cmask))
add_shift_mask >>= 1
condition_mask &= ~add_val_mask
add_val_mask <<= 1
if reverse_to_subtract:
ops.reverse()
for inst in ops:
op_qubits = [x for x in condition_qubits]
mask = 1
for i in range(len(qdest)):
if inst[1] & (1 << i):
op_qubits.append(qdest[i])
for i in range(len(qdest)):
if inst[0] & (1 << i):
op_qubits.append(qdest[i])
multi_cx(op_qubits)
def multi_cz(qubits):
## This will perform a CCCCCZ on as many qubits as we want,
## as long as we have enough scratch qubits
multi_cx(qubits, do_cz=True)
def multi_cx(qubits, do_cz=False):
## This will perform a CCCCCX with as many conditions as we want,
## as long as we have enough scratch qubits
## The last qubit in the list is the target.
target = qubits[-1]
conds = qubits[:-1]
scratch_index = 0
ops = []
while len(conds) > 2:
new_conds = []
for i in range(len(conds)//2):
ops.append((conds[i * 2], conds[i * 2 + 1], scratch[scratch_index]))
new_conds.append(scratch[scratch_index])
scratch_index += 1
if len(conds) & 1:
new_conds.append(conds[-1])
conds = new_conds
for op in ops:
qc.ccx(op[0], op[1], op[2])
if do_cz:
qc.h(target)
if len(conds) == 0:
qc.x(target)
elif len(conds) == 1:
qc.cx(conds[0], target)
else:
qc.ccx(conds[0], conds[1], target)
if do_cz:
qc.h(target)
ops.reverse()
for op in ops:
qc.ccx(op[0], op[1], op[2])
main()
## That's the program. Everything below runs and draws it.
backend = BasicAer.get_backend('statevector_simulator')
job = execute(qc, backend)
result = job.result()
outputstate = result.get_statevector(qc, decimals=3)
for i,amp in enumerate(outputstate):
if abs(amp) > 0.000001:
print('|{}> {}'.format(i, amp))
qc.draw() # draw the circuit
|13> (0.5+0j) |17> (0.5+0j) |29> 0.5j |33> 0.5j
## Example 5-5: Quantum conditional phase flip
## Note that this looks different from the gates in the book, because
## we're building the operations from Toffoli gates
# Set up the program
a = QuantumRegister(3, name='a')
b = QuantumRegister(2, name='b')
qc = QuantumCircuit(a, b)
def main():
## initialization
qc.h(a[0])
qc.h(a[1])
qc.x(b[0])
qc.h(b[1])
qc.barrier()
## Increment
add_int(a, -3)
qc.barrier()
qc.x(b[1])
multi_cz([a[2], b[0], b[1]])
qc.x(b[1])
qc.barrier()
add_int(a, 3)
###############################################
## Some utility functions
def add_squared_qint(qdest, rhs, condition_qubits=None):
if condition_qubits is None:
condition_qubits = []
for bit in range(len(rhs)):
slideMask = list(set(condition_qubits + [rhs[bit]]))
add_qint(qdest, rhs, slideMask, bit);
def add_qint(qdest, rhs, condition_qubits=None, shiftRHS=0):
if condition_qubits is None:
condition_qubits = []
for bit in range(len(rhs)):
add_int(qdest, 1 << bit, list(set([rhs[bit]] + condition_qubits)), shiftRHS)
def add_int(qdest, rhs, condition_qubits=None, shiftRHS=0):
if condition_qubits is None:
condition_qubits = []
reverse_to_subtract = False
if rhs == 0:
return
elif rhs < 0:
rhs = -rhs
reverse_to_subtract = True
rhs <<= shiftRHS
ops = []
add_val = int(rhs)
condition_mask = (1 << len(qdest)) - 1
add_val_mask = 1
while add_val_mask <= add_val:
cmask = condition_mask & ~(add_val_mask - 1)
if add_val_mask & add_val:
add_shift_mask = 1 << (len(qdest) - 1)
while add_shift_mask >= add_val_mask:
cmask &= ~add_shift_mask
ops.append((add_shift_mask, cmask))
add_shift_mask >>= 1
condition_mask &= ~add_val_mask
add_val_mask <<= 1
if reverse_to_subtract:
ops.reverse()
for inst in ops:
op_qubits = [x for x in condition_qubits]
mask = 1
for i in range(len(qdest)):
if inst[1] & (1 << i):
op_qubits.append(qdest[i])
for i in range(len(qdest)):
if inst[0] & (1 << i):
op_qubits.append(qdest[i])
multi_cx(op_qubits)
def multi_cz(qubits):
## This will perform a CCCCCZ on as many qubits as we want,
## as long as we have enough scratch qubits
multi_cx(qubits, do_cz=True)
def multi_cx(qubits, do_cz=False):
## This will perform a CCCCCX with as many conditions as we want,
## as long as we have enough scratch qubits
## The last qubit in the list is the target.
target = qubits[-1]
conds = qubits[:-1]
scratch_index = 0
ops = []
while len(conds) > 2:
new_conds = []
for i in range(len(conds)//2):
ops.append((conds[i * 2], conds[i * 2 + 1], scratch[scratch_index]))
new_conds.append(scratch[scratch_index])
scratch_index += 1
if len(conds) & 1:
new_conds.append(conds[-1])
conds = new_conds
for op in ops:
qc.ccx(op[0], op[1], op[2])
if do_cz:
qc.h(target)
if len(conds) == 0:
qc.x(target)
elif len(conds) == 1:
qc.cx(conds[0], target)
else:
qc.ccx(conds[0], conds[1], target)
if do_cz:
qc.h(target)
ops.reverse()
for op in ops:
qc.ccx(op[0], op[1], op[2])
main()
## That's the program. Everything below runs and draws it.
backend = BasicAer.get_backend('statevector_simulator')
job = execute(qc, backend)
result = job.result()
outputstate = result.get_statevector(qc, decimals=3)
for i,amp in enumerate(outputstate):
if abs(amp) > 0.000001:
print('|{}> {}'.format(i, amp))
qc.draw() # draw the circuit
|8> (-0.354+0j) |9> (-0.354+0j) |10> (-0.354+0j) |11> (0.354+0j) |24> (0.354+0j) |25> (0.354+0j) |26> (0.354+0j) |27> (0.354+0j)
## Example 5-6: CNOT Logic
# Set up the program
a = QuantumRegister(1, name='a')
b = QuantumRegister(1, name='b')
c = QuantumRegister(1, name='c')
r1 = ClassicalRegister(1, name='r1')
r2 = ClassicalRegister(2, name='r2')
r3 = ClassicalRegister(3, name='r3')
qc = QuantumCircuit(a, b, c, r1, r2, r3)
## initialization
qc.reset(c)
qc.x(c)
qc.measure(c, r1)
qc.barrier()
qc.reset(b)
qc.reset(c)
qc.x(b)
qc.cx(b, c)
qc.measure(b, r2[0])
qc.measure(c, r2[1])
qc.barrier()
qc.reset(a)
qc.reset(b)
qc.reset(c)
qc.x(a)
qc.x(b)
qc.ccx(a, b, c)
qc.measure(a, r3[0])
qc.measure(b, r3[1])
qc.measure(c, r3[2])
## That's the program. Everything below runs and draws it.
backend = BasicAer.get_backend('statevector_simulator')
job = execute(qc, backend)
result = job.result()
counts = result.get_counts(qc)
print('counts:',counts)
outputstate = result.get_statevector(qc, decimals=3)
for i,amp in enumerate(outputstate):
if abs(amp) > 0.000001:
print('|{}> {}'.format(i, amp))
qc.draw() # draw the circuit
counts: {'111 11 1': 1} |7> (1+0j)
## More chapter 5 samples coming soon!