View on GitHub
Open this notebook in GitHub to run it yourself
PyTket code for QSVT example
This notebook shows how to generate data for discrete quantum walk usingpytket 1.34.0
Here we provide the codes for block encoding the matrix A, as well as the QSVT implementation. PyTket does not have an adder by a constant function. Thus, we have modified their adder functions, which is applied between two quantum registers, to include this functionality.
Copy
Ask AI
# import time
# from pytket.circuit import Circuit, CircBox, OpType, QControlBox
# from pytket.extensions.qiskit import AerBackend
# from pytket.passes import DecomposeBoxes, SynthesiseTket
Copy
Ask AI
# backend = AerBackend()
# from pytket.circuit import Circuit, CircBox
# import numpy as np
# def build_qft_circuit(n_qubits: int, do_swaps: True) -> Circuit:
# circ = Circuit(n_qubits, name="QFT")
# for i in range(n_qubits):
# circ.H(i)
# for j in range(i + 1, n_qubits):
# circ.CU1(1 / 2 ** (j - i), j, i)
# if do_swaps:
# for k in range(0, n_qubits // 2):
# circ.SWAP(k, n_qubits - k - 1)
# return circ
# class DraperQFTAdderConstantPytket:
# def __init__(self, num_state_qubits: int, constant: int) -> Circuit:
# circuit = Circuit(num_state_qubits)
# qft_circuit = build_qft_circuit(num_state_qubits, do_swaps=False)
# circuit.add_gate(CircBox(qft_circuit),[k for k in range(num_state_qubits)])
# # Apply phase rotations for the constant
# for qubit in range(num_state_qubits):
# angle = (constant % (2 ** (qubit + 1))) * np.pi / (2 ** qubit)
# circuit.Rz(angle, qubit)
# # Apply inverse QFT
# circuit.add_gate(CircBox(qft_circuit).dagger,[k for k in range(num_state_qubits)])
# self.circuit = circuit
# def get_circuit(self) -> Circuit:
# return self.circuit
Copy
Ask AI
# def get_reflect_around_zero(size):
# qc = Circuit(size, name="reflection")
# qc.X(0)
# qc.H(0)
# qc.add_gate(QControlBox(CircBox(Circuit(1).X(0)), n_controls = size-1, control_state=[0]*(size-1)), [k for k in range(size)])
# qc.H(0)
# qc.X(0)
# return qc
# def get_cir_be(qc, data, block):
# qc.H(block[0])
# qc.H(block[2])
# adder_2_cir = DraperQFTAdderConstantPytket(len(data)+1, 2).get_circuit()
# adder_1_cir = DraperQFTAdderConstantPytket(len(data)+1, -1+2**(len(data)+1)).get_circuit()
# qc.add_gate(QControlBox(CircBox(adder_2_cir), n_controls = 1, control_state=0), [block[0]]+[data[k] for k in range(len(data))]+[block[1]])
# qc.add_gate(CircBox(adder_1_cir), [data[k] for k in range(len(data))]+[block[1]])
# qc.add_gate(QControlBox(CircBox(get_reflect_around_zero(len(data))),n_controls=1, control_state=0),[block[2]]+[data[k] for k in range(len(data))])
# qc.H(block[0])
# qc.H(block[2])
# return qc
# def apply_projector_controlled_phase(qc, phase, block_reg, aux_reg):
# qc.add_gate(QControlBox(CircBox(Circuit(1).X(0)), n_controls = len(block_reg), control_state=[0]*len(block_reg)),
# [block_reg[k] for k in range(len(block_reg))] + [aux_reg[0]]
# )
# qc.Rz(phase, aux_reg[0])
# qc.add_gate(QControlBox(CircBox(Circuit(1).X(0)), n_controls = len(block_reg), control_state=[0]*len(block_reg)),
# [block_reg[k] for k in range(len(block_reg))] + [aux_reg[0]]
# )
# def apply_qsvt_step(qc, phase1, phase2, u, data, block, qsvt_aux):
# qc.add_gate(CircBox(u), [data[l] for l in range(len(data))]+ [block[l] for l in range(len(block))])
# apply_projector_controlled_phase(qc, phase1, block, qsvt_aux)
# qc.add_gate(CircBox(u).dagger, [data[l] for l in range(len(data))]+ [block[l] for l in range(len(block))])
# apply_projector_controlled_phase(qc, phase2, block, qsvt_aux)
# def get_qsvt_circuit(qsvt_phases,
# size):
# qsvt_cir = Circuit()
# data = qsvt_cir.add_q_register("data", size)
# block = qsvt_cir.add_q_register("block", 3)
# cir_be = Circuit()
# data = cir_be.add_q_register("data", size)
# block = cir_be.add_q_register("block", 3)
# qsvt_aux = qsvt_cir.add_q_register("qsvt_aux", 1)
# cir_be = get_cir_be(cir_be,data, block)
# qsvt_cir.H(qsvt_aux[0])
# apply_projector_controlled_phase(qsvt_cir, qsvt_phases[0], block, qsvt_aux)
# for i in range(int(np.floor((len(qsvt_phases) - 1) / 2))):
# apply_qsvt_step(qsvt_cir,
# qsvt_phases[(2 * i) + 1], qsvt_phases[(2 * i) + 2],
# cir_be,
# data,
# block,
# qsvt_aux
# )
# qsvt_cir.add_gate(CircBox(cir_be), [data[l] for l in range(len(data))]+ [block[l] for l in range(len(block))])
# apply_projector_controlled_phase(qsvt_cir, qsvt_phases[len(qsvt_phases) - 1], block, qsvt_aux)
# qsvt_cir.H(qsvt_aux[0])
# return qsvt_cir
run an example
Copy
Ask AI
# SIZE = 6
# DEGREE = 3
# QSVT_PHASES = [1.280311896404252, 8.127145628464149, 1.8439603212845617, -5.002873410775335]
# start_time = time.time()
# qc_qsvt = get_qsvt_circuit(QSVT_PHASES, SIZE)
# DecomposeBoxes().apply(qc_qsvt)
# SynthesiseTket().apply(qc_qsvt)
# compiled_circ = backend.get_compiled_circuit(qc_qsvt)
# transpilation_time = time.time()-start_time
# depth = compiled_circ.depth()
# cx_counts = compiled_circ.n_gates_of_type(OpType.CX)
# width = compiled_circ.n_qubits
# print(f"==== tket for {SIZE}==== time: {transpilation_time}")