Source code for quforge.circuit

import torch.nn as nn
import quforge.gates as gates


[docs]class Circuit(nn.Module): r""" Quantum Circuit for qudits. The Circuit class allows users to dynamically add various quantum gates to construct a quantum circuit for qudit systems. It supports a wide range of gates, including single-qudit, multi-qudit, and custom gates. The circuit is represented as a sequence of quantum operations (gates) that act on qudit states. **Arguments:** dim (int or list of int): The dimension of the qudits. If an integer, all qudits are assumed to have that dimension; if a list is provided, each element specifies the dimension of the corresponding qudit. wires (int): The total number of qudits (wires) in the circuit (used when `dim` is an integer). If `dim` is a list, wires is taken as the length of that list. device (str): The device to perform the computations on. Default is 'cpu'. sparse (bool): Whether to use sparse matrix representations for the gates. Default is False. **Attributes:** dim (int or list of int): The dimension(s) of the qudits. wires (int): The number of qudits in the circuit. device (str): The device for computations ('cpu' or 'cuda'). circuit (nn.Sequential): A sequential container for holding the quantum gates. sparse (bool): Whether to use sparse matrices in the gates. **Methods:** add(module, **kwargs): Dynamically add a gate module to the circuit. add_gate(gate, **kwargs): Add a specific gate instance to the circuit. H(**kwargs): Add a Hadamard gate to the circuit. X(**kwargs): Add a Pauli-X gate to the circuit. Y(**kwargs): Add a Pauli-Y gate to the circuit. Z(**kwargs): Add a Pauli-Z gate to the circuit. RX(**kwargs): Add a rotation-X gate to the circuit. RY(**kwargs): Add a rotation-Y gate to the circuit. RZ(**kwargs): Add a rotation-Z gate to the circuit. CNOT(**kwargs): Add a controlled-NOT gate to the circuit. SWAP(**kwargs): Add a SWAP gate to the circuit. CZ(**kwargs): Add a controlled-Z gate to the circuit. CCNOT(**kwargs): Add a Toffoli (CCNOT) gate to the circuit. MCX(**kwargs): Add a multi-controlled-X gate to the circuit. CRX(**kwargs): Add a controlled rotation-X gate to the circuit. CRY(**kwargs): Add a controlled rotation-Y gate to the circuit. CRZ(**kwargs): Add a controlled rotation-Z gate to the circuit. U(**kwargs): Add a universal gate to the circuit. CU(**kwargs): Add a controlled-universal gate to the circuit. **Example:** >>> import quforge.quforge as qf >>> circuit = qf.Circuit(dim=[2,3,2], wires=3, device='cpu') # Multidimensional: qudit0:2, qudit1:3, qudit2:2 >>> circuit.H(index=[0]) >>> circuit.CNOT(index=[0, 1]) >>> state = qf.State('0-1-0', dim=[2,3,2]) >>> result = circuit(state) >>> print(result) """ def __init__(self, dim=2, wires=1, device="cpu", sparse=False): super(Circuit, self).__init__() # Process dimensions: if dim is a list, use its length as wires. if isinstance(dim, int): self.dim = dim self.wires = wires else: self.dim = dim self.wires = len(dim) self.device = device self.circuit = nn.Sequential() self.sparse = sparse
[docs] def add(self, module, **kwargs): """ Dynamically add a gate module to the circuit. Args: module: The gate module to add. **kwargs: Additional arguments for the gate. """ gate = module( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) self.circuit.add_module(str(len(self.circuit)), gate)
[docs] def add_gate(self, gate, **kwargs): """ Add a pre-instantiated gate to the circuit. Args: gate: The gate instance to add. **kwargs: Additional arguments for the gate. """ self.circuit.add_module(str(len(self.circuit)), gate)
[docs] def H(self, **kwargs): self.add_gate( gates.H(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def X(self, **kwargs): self.add_gate( gates.X(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def Y(self, **kwargs): self.add_gate( gates.Y(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def Z(self, **kwargs): self.add_gate( gates.Z(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def RX(self, **kwargs): self.add_gate( gates.RX( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) )
[docs] def RY(self, **kwargs): self.add_gate( gates.RY( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) )
[docs] def RZ(self, **kwargs): self.add_gate( gates.RZ( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) )
[docs] def CNOT(self, **kwargs): self.add_gate( gates.CNOT( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) )
[docs] def SWAP(self, **kwargs): self.add_gate( gates.SWAP(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def CZ(self, **kwargs): self.add_gate( gates.CZ(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def CCNOT(self, **kwargs): self.add_gate( gates.CCNOT(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def MCX(self, **kwargs): self.add_gate( gates.MCX(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def CRX(self, **kwargs): self.add_gate( gates.CRX( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) )
[docs] def CRY(self, **kwargs): self.add_gate( gates.CRY( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) )
[docs] def CRZ(self, **kwargs): self.add_gate( gates.CRZ( dim=self.dim, wires=self.wires, device=self.device, sparse=self.sparse, **kwargs ) )
[docs] def U(self, **kwargs): self.add_gate( gates.U(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def CU(self, **kwargs): self.add_gate( gates.CU(dim=self.dim, wires=self.wires, device=self.device, **kwargs) )
[docs] def forward(self, x): """ Apply the circuit to the input qudit state. Args: x (torch.Tensor): The input qudit state (a column vector) whose dimension equals the product of the individual qudit dimensions. Returns: torch.Tensor: The resulting state after applying the circuit. """ return self.circuit(x)