Skip to content

Commit

Permalink
added support for PauliTwoDesign
Browse files Browse the repository at this point in the history
  • Loading branch information
01110011011101010110010001101111 committed Aug 4, 2023
1 parent 60779d0 commit 4172965
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 15 deletions.
41 changes: 41 additions & 0 deletions torchquantum/layer/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"RandomLayer",
"RandomLayerAllTypes",
"Op1QAllLayer",
"RandomOp1All",
"Op2QAllLayer",
"Op2QButterflyLayer",
"Op2QDenseLayer",
Expand Down Expand Up @@ -146,6 +147,46 @@ def forward(self, q_device: tq.QuantumDevice):
self.op(q_device, wires=[self.n_gate - 1, 0])


class RandomOp1All(tq.QuantumModule):
def __init__(
self, n_wires: int, op_types=(tq.RX, tq.RY, tq.RZ), op_ratios=None, seed=None
):
"""Layer adding a random gate to all wires
Params:
n_wires (int): number of wires/gates in integer format
op_types (Iterable): single-wire gates to select from in iterable format
op_ratios (Iterable): probabilities to select each gate option in iterable format
seed (int): random seed in integer format
"""
super().__init__()
self.n_wires = n_wires
self.op_types = op_types
self.op_ratios = op_ratios
self.seed = seed
self.gate_all = nn.ModuleList()
if seed is not None:
np.random.seed(seed)
self.build_random_layer()

def build_random_layer(self):
for k in range(self.n_wires):
op = np.random.choice(self.op_types, p=self.op_ratios)
self.gate_all.append(op())

@tq.static_support
def forward(self, q_device: tq.QuantumDevice, x):
# op on all wires, assert the number of gate is the same as the number
# of wires in the device.
assert self.n_gate == q_device.n_wires, (
f"Number of gates ({self.n_wires}) is different from number "
f"of wires ({q_device.n_wires})!"
)

for k in range(self.n_wires):
self.gate_all[k](q_device, wires=k, params=x[:, k])


class RandomLayer(tq.QuantumModule):
def __init__(
self,
Expand Down
89 changes: 74 additions & 15 deletions torchquantum/layer/nlocal.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,27 @@
SOFTWARE.
"""

import torchquantum as tq
import torchquantum.layers as layers


class NLocal(layers.LayerTemplate0):
import torch
import torchquantum as tq
from torchquantum.layer.layers import (
LayerTemplate0,
Op1QAllLayer,
Op2QAllLayer,
RandomOp1All,
)

__all__ = [
"NLocal",
"TwoLocal",
"ExcitationPreserving",
"EfficientSU2",
"RealAmplitudes",
"PauliTwoDesign",
]


class NLocal(LayerTemplate0):
"""Layer Template for a NLocal Class
Args:
Expand All @@ -44,11 +60,11 @@ class NLocal(layers.LayerTemplate0):

def __init__(
self,
rotation_ops: list,
entanglement_ops: list,
rotation_ops: list = None,
entanglement_ops: list = None,
arch: dict = None,
rotation_layer: tq.QuantumModule = tq.layers.Op1QAllLayer,
entanglement_layer: tq.QuantumModule = tq.layers.Op2QAllLayer,
rotation_layer: tq.QuantumModule = Op1QAllLayer,
entanglement_layer: tq.QuantumModule = Op2QAllLayer,
reps: int = 1,
rotation_layer_params: dict = {},
entanglement_layer_params: dict = {},
Expand Down Expand Up @@ -143,10 +159,10 @@ class TwoLocal(NLocal):

def __init__(
self,
rotation_ops: list,
entanglement_ops: list,
rotation_ops: list = None,
entanglement_ops: list = None,
arch: dict = None,
rotation_layer: tq.QuantumModule = tq.layers.Op1QAllLayer,
rotation_layer: tq.QuantumModule = Op1QAllLayer,
entanglement_layer: str = "linear",
reps: int = 1,
entanglement_layer_params: dict = {},
Expand All @@ -155,15 +171,15 @@ def __init__(
):
# if passed as string, determine entanglement type
if entanglement_layer == "linear":
entanglement_layer = tq.layers.Op2QAllLayer
entanglement_layer = Op2QAllLayer
elif entanglement_layer == "reverse_linear":
entanglement_layer = tq.layers.Op2QAllLayer
entanglement_layer = Op2QAllLayer
entanglement_layer_params = {"wire_reverse": True}
elif entanglement_layer == "circular":
entanglement_layer = tq.layers.Op2QAllLayer
entanglement_layer = Op2QAllLayer
entanglement_layer_params = {"circular": True}
elif entanglement_layer == "full":
entanglement_layer = tq.layers.Op2QDenseLayer
entanglement_layer = Op2QDenseLayer

# initialize
super().__init__(
Expand Down Expand Up @@ -263,3 +279,46 @@ def __init__(
reps=reps,
skip_final_rotation_layer=skip_final_rotation_layer,
)


class PauliTwoDesign(TwoLocal):
"""Layer Template for a PauliTwoDesign circuit
Args:
arch (dict): circuit architecture in a dictionary format
entanglement_layer (str): type of entanglement layer in a string ("linear", "reverse_linear", "circular", "full") or tq.QuantumModule format
reps (int): number of reptitions of the rotation and entanglement layers in a integer format
skip_final_rotation_layer (bool): whether or not to add the final rotation layer as a boolean
"""

def __init__(
self,
arch: dict = None,
entanglement_layer: str = "reverse_linear",
reps: int = 3,
skip_final_rotation_layer: bool = False,
seed: int = 0,
):
# set seed
self.seed = seed
# construct circuit with entanglement with CX
super().__init__(
arch=arch,
entanglement_ops=[tq.CNOT],
entanglement_layer=entanglement_layer,
reps=reps,
skip_final_rotation_layer=skip_final_rotation_layer,
)

def build_initial_layer(self):
# add an initial layer of ry with rotation pi/4
return tq.QuantumModule.from_op_history(
[
{"name": "ry", "wires": wire, "params": torch.pi / 4}
for wire in range(self.arch["n_wires"])
]
)

def build_rotation_block(self):
# make a random layer of rotations
return [RandomOp1All(n_wires=self.n_wires, seed=self.seed)]

0 comments on commit 4172965

Please sign in to comment.