1""" ORCA layer module """
2from typing import Literal
3from ptseries.models import PTLayer
4from torch import nn
5import torch
6import numpy as np
7
8from qailab.orca_api.pt_adapter import PTAdapter
9
10
[docs]
11class ORCALayer(nn.Module):
12 """Neural Network layer using ORCA quantum computers, a PTLayer wrapper
13
14 Parameters
15 ----------
16 in_features: int,
17 number fo layer input features
18 observable: Literal['avg-photons', 'covariances', 'correlations'], default = 'avg-photons'
19 method of conversion from measurements to a tensor. Default is "avg-photons".
20 gradient_mode: Literal['parameter-shift', 'finite-difference', 'spsa'], default = 'parameter-shift',
21 method to compute the gradient. Default is "parameter-shift".
22 gradient_delta: float, default = np.pi / 10
23 Delta to use with the parameter shift rule or for the finite difference. Default is np.pi / 10.
24 n_samples: int, default = 100
25 Number of samples to draw. Default is 100.
26 n_tiling: int, default = 1
27 Uses n_tiling instances of PT Series and concatenates the results.
28 Input features are distributed between tiles, which each have different trainable params. Default is 1.
29 tbi_type: Literal['multi-loop', 'single-loop', 'fixed-random-unitary', 'PT'], default = 'single-loop'
30 Type of TBI to return. Can be 'multi-loop', 'single-loop', 'fixed-random-unitary' or 'PT.
31 Choose PT to run on real PT device. Default is 'single-loop'.
32 n_loops: int, default = 1
33 Number of loops in the TBI. Default it 1.
34 url: str, default = None
35 The URL of the PT device, for example "http://<orca_api_address>".
36 tbi_params: dict, default = None
37 Dictionary of optional parameters to instantiate the TBI. Default is None.
38 """
39
40 def __init__(self,
41 in_features: int,
42 observable: Literal['avg-photons', 'covariances', 'correlations'] = "avg-photons",
43 gradient_mode: Literal['parameter-shift', 'finite-difference', 'spsa'] = 'parameter-shift',
44 gradient_delta: float = np.pi / 10,
45 n_samples: int = 100,
46 n_tiling: int = 1,
47 tbi_type: str | None = None,
48 n_loops: int | None = None,
49 url: str | None = None,
50 machine: str | None = None,
51 secret_key: str | None = None,
52 **tbi_params) -> None:
53 super().__init__()
54 input_state = list(map(lambda x: x % 2, range(in_features + 1)))
55 self.pt_layer = PTLayer(input_state=input_state, in_features=in_features, observable=observable, gradient_mode=gradient_mode,
56 gradient_delta=gradient_delta, n_samples=n_samples,
57 tbi_params=tbi_params | {"tbi_type": tbi_type, "n_loops": n_loops, "url": url}, n_tiling=n_tiling)
58 if tbi_type == "PT":
59 if url is None or machine is None or secret_key is None:
60 raise ValueError('Parameters url, machine and secret key need to be provided to use real PT device')
61 if n_loops is None:
62 n_loops = 1
63 self.pt_layer.tbi = PTAdapter(n_loops=n_loops, url=url, machine=machine, secret_key=secret_key, **tbi_params)
64
[docs]
65 def forward(self, x: torch.Tensor | None = None, n_samples: int | None = None) -> torch.Tensor:
66 """ORCA layer pytorch Module forward method
67
68 Parameters
69 ----------
70 x: torch.Tensor | None, default = None.
71 layer input tensor
72 n_samples: int | None, default = None.
73 number of samples from quantum computer
74
75 Returns
76 -------
77 output: torch.Tensor
78 layer output tensor
79 """
80 return self.pt_layer.forward(x, n_samples) # type: ignore
81
[docs]
82 def set_thetas(self, theta_values: torch.Tensor):
83 """set theta parameters of layer's beam splitter gates
84
85 Parameters
86 ----------
87 theta_values: torch.Tensor
88 values of theta parameter of layer's beam splitter gates
89 """
90 self.pt_layer.set_thetas(theta_values)