Source code for torchquantum.layer.layers.qft_layer

import torch
import torch.nn as nn
import torchquantum as tq
import torchquantum.functional as tqf
import numpy as np

from typing import Iterable
from torchquantum.plugin.qiskit import QISKIT_INCOMPATIBLE_FUNC_NAMES
from torchpack.utils.logging import logger

[docs]class QFTLayer(tq.QuantumModule):
[docs] def __init__( self, n_wires: int = None, wires: Iterable = None, do_swaps: bool = True, inverse: bool = False, ): """ Constructs a Quantum Fourier Transform (QFT) layer Args: n_wires (int): Number of wires for the QFT as an integer wires (Iterable): Wires to perform the QFT as an Iterable do_swaps (bool): Whether or not to add the final swaps in a boolean format inverse (bool): Whether to create an inverse QFT layer in a boolean format """ super().__init__() assert n_wires is not None or wires is not None if n_wires is None: self.n_wires = len(wires) if wires is None: wires = range(n_wires) self.n_wires = n_wires self.wires = wires self.do_swaps = do_swaps if inverse: self.gates_all = self.build_inverse_circuit() else: self.gates_all = self.build_circuit()
[docs] def build_circuit(self): """Construct a QFT circuit.""" operation_list = [] # add the H and CU1 gates for top_wire in range(self.n_wires): operation_list.append({"name": "hadamard", "wires": self.wires[top_wire]}) for wire in range(top_wire + 1, self.n_wires): lam = torch.pi / (2 ** (wire - top_wire)) operation_list.append( { "name": "cu1", "params": lam, "wires": [self.wires[wire], self.wires[top_wire]], } ) # add swaps if specified if self.do_swaps: for wire in range(self.n_wires // 2): operation_list.append( { "name": "swap", "wires": [ self.wires[wire], self.wires[self.n_wires - wire - 1], ], } ) return tq.QuantumModule.from_op_history(operation_list)
[docs] def build_inverse_circuit(self): """Construct the inverse of a QFT circuit.""" operation_list = [] # add swaps if specified if self.do_swaps: for wire in range(self.n_wires // 2): operation_list.append( { "name": "swap", "wires": [ self.wires[wire], self.wires[self.n_wires - wire - 1], ], } ) # add the CU1 and H gates for top_wire in range(self.n_wires)[::-1]: for wire in range(top_wire + 1, self.n_wires)[::-1]: lam = -torch.pi / (2 ** (wire - top_wire)) operation_list.append( { "name": "cu1", "params": lam, "wires": [self.wires[wire], self.wires[top_wire]], } ) operation_list.append({"name": "hadamard", "wires": self.wires[top_wire]}) return tq.QuantumModule.from_op_history(operation_list)
[docs] @tq.static_support def forward(self, q_device: tq.QuantumDevice): self.gates_all(q_device)