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)