Source code for qailab.circuit.encoding_blocks.rotational
1"""R-gate implementations of input vector encoding blocks for variational circuits."""
2from typing import Literal
3from collections.abc import Callable
4
5from qiskit import QuantumCircuit
6from qiskit.circuit.library import RealAmplitudes
7
8from qailab.circuit.base import EncodingBlock, EntanglingBlock
9
10
[docs]
11class RotationalEncoder(EncodingBlock):
12 """
13 Encoding of input vector using rotational gates.
14
15 Attributes:
16 r_gate_type (Literal['x', 'y', 'z']): Type of rotational gate applied to each qubit.
17 block_type (Literal['input', 'weight']): Whether this block encodes weights or inputs.
18 """
19
20 def __init__(self, r_gate_type: Literal['x', 'y', 'z'], block_type: Literal['input', 'weight']) -> None:
21 self.r_gate_type: Literal['x', 'y', 'z'] = r_gate_type
22 super().__init__(f"R{r_gate_type}Encoder", block_type)
23
24 def _build_circuit(self, num_qubits: int) -> QuantumCircuit:
25 # Don't create new parameter vectors. This would enable the user to encode the same vector in different parts of the circuit.
26 if self._parameters is None:
27 self._parameters = self._create_parameters(num_qubits)
28
29 circuit = QuantumCircuit(num_qubits)
30 match self.r_gate_type:
31 case 'x':
32 fn = circuit.rx
33 case 'y':
34 fn = circuit.ry
35 case 'z':
36 fn = circuit.rz
37 case _:
38 raise ValueError(f"'{self.r_gate_type}' is not a valid rotational gate type")
39 for i in range(num_qubits):
40 fn(self._parameters[i], i)
41
42 return circuit
43
44
[docs]
45class RealAmplitudesBlock(EncodingBlock, EntanglingBlock):
46 """
47 Block wrapper for RealAmplitudes from qiskit.circuit.library
48 """
49
50 def __init__(
51 self,
52 block_type: Literal['input', 'weight'],
53 entanglement: str | list[list[int]] | Callable[[int], list[int]] = "reverse_linear",
54 reps: int = 3,
55 skip_final_rotation_layer: bool = False
56 ) -> None:
57 self.entanglement = entanglement
58 self.reps = reps
59 self.skip_final_rotation_layer = skip_final_rotation_layer
60 super().__init__("RealAmplitudesEncoder", block_type)
61
62 def _build_circuit(self, num_qubits: int) -> QuantumCircuit:
63 pv_name = self._create_parameters(1)[0].name
64 amplitudes = RealAmplitudes(
65 num_qubits,
66 parameter_prefix=pv_name,
67 entanglement=self.entanglement,
68 reps=self.reps,
69 skip_final_rotation_layer=self.skip_final_rotation_layer,
70 )
71 self._parameters = list(amplitudes.parameters)
72 return amplitudes