3
3
import numpy as np
4
4
import tensorflow as tf
5
5
from qibo .base import circuit
6
- from qibo .config import DTYPES
6
+ from qibo .config import DTYPES , DEVICES
7
7
from qibo .tensorflow import measurements
8
8
from qibo .tensorflow import custom_operators as op
9
9
from typing import List , Optional , Tuple , Union
10
+ InitStateType = Union [np .ndarray , tf .Tensor ]
11
+ OutputType = Union [tf .Tensor , measurements .CircuitResult ]
10
12
11
13
12
14
class TensorflowCircuit (circuit .BaseCircuit ):
@@ -20,6 +22,13 @@ def __init__(self, nqubits):
20
22
super (TensorflowCircuit , self ).__init__ (nqubits )
21
23
self ._compiled_execute = None
22
24
25
+ def _set_nqubits (self , gate ):
26
+ if gate ._nqubits is None :
27
+ with tf .device (DEVICES ['DEFAULT' ]):
28
+ gate .nqubits = self .nqubits
29
+ elif gate .nqubits != self .nqubits :
30
+ super (TensorflowCircuit , self )._set_nqubits (gate )
31
+
23
32
def _eager_execute (self , state : tf .Tensor ) -> tf .Tensor :
24
33
"""Simulates the circuit gates in eager mode."""
25
34
for gate in self .queue :
@@ -66,34 +75,9 @@ def using_tfgates(self) -> bool:
66
75
from qibo .tensorflow import gates
67
76
return gates .TensorflowGate == self .gate_module .TensorflowGate
68
77
69
- def execute (self ,
70
- initial_state : Optional [Union [np .ndarray , tf .Tensor ]] = None ,
71
- nshots : Optional [int ] = None ,
72
- ) -> Union [tf .Tensor , measurements .CircuitResult ]:
73
- """Propagates the state through the circuit applying the corresponding gates.
74
-
75
- In default usage the full final state vector or density matrix is returned.
76
- If the circuit contains measurement gates and `nshots` is given, then
77
- the final state is sampled and the samples are returned.
78
- Circuit execution uses by default state vectors but switches automatically
79
- to density matrices if
80
-
81
- Args:
82
- initial_state (np.ndarray): Initial state vector as a numpy array of shape ``(2 ** nqubits,)``
83
- or a density matrix of shape ``(2 ** nqubits, 2 ** nqubits)``.
84
- A Tensorflow tensor with shape ``nqubits * (2,)`` (or ``2 * nqubits * (2,)`` for density matrices)
85
- is also allowed as an initial state but must have the `dtype` of the circuit.
86
- If ``initial_state`` is ``None`` the |000...0> state will be used.
87
- nshots (int): Number of shots to sample if the circuit contains
88
- measurement gates.
89
- If ``nshots`` None the measurement gates will be ignored.
90
-
91
- Returns:
92
- If ``nshots`` is given and the circuit contains measurements
93
- A :class:`qibo.base.measurements.CircuitResult` object that contains the measured bitstrings.
94
- If ``nshots`` is ``None`` or the circuit does not contain measurements.
95
- The final state vector as a Tensorflow tensor of shape ``(2 ** nqubits,)`` or a density matrix of shape ``(2 ** nqubits, 2 ** nqubits)``.
96
- """
78
+ def _execute (self , initial_state : Optional [InitStateType ] = None ,
79
+ nshots : Optional [int ] = None ) -> OutputType :
80
+ """Performs ``circuit.execute`` on specified device."""
97
81
state = self ._cast_initial_state (initial_state )
98
82
99
83
if self .using_tfgates :
@@ -124,8 +108,44 @@ def execute(self,
124
108
return measurements .CircuitResult (
125
109
self .measurement_tuples , self .measurement_gate_result )
126
110
127
- def __call__ (self , initial_state : Optional [tf .Tensor ] = None ,
128
- nshots : Optional [int ] = None ) -> tf .Tensor :
111
+ def execute (self , initial_state : Optional [InitStateType ] = None ,
112
+ nshots : Optional [int ] = None ) -> OutputType :
113
+ """Propagates the state through the circuit applying the corresponding gates.
114
+
115
+ In default usage the full final state vector or density matrix is returned.
116
+ If the circuit contains measurement gates and `nshots` is given, then
117
+ the final state is sampled and the samples are returned.
118
+ Circuit execution uses by default state vectors but switches automatically
119
+ to density matrices if
120
+
121
+ Args:
122
+ initial_state (np.ndarray): Initial state vector as a numpy array of shape ``(2 ** nqubits,)``
123
+ or a density matrix of shape ``(2 ** nqubits, 2 ** nqubits)``.
124
+ A Tensorflow tensor with shape ``nqubits * (2,)`` (or ``2 * nqubits * (2,)`` for density matrices)
125
+ is also allowed as an initial state but must have the `dtype` of the circuit.
126
+ If ``initial_state`` is ``None`` the |000...0> state will be used.
127
+ nshots (int): Number of shots to sample if the circuit contains
128
+ measurement gates.
129
+ If ``nshots`` None the measurement gates will be ignored.
130
+
131
+ Returns:
132
+ If ``nshots`` is given and the circuit contains measurements
133
+ A :class:`qibo.base.measurements.CircuitResult` object that contains the measured bitstrings.
134
+ If ``nshots`` is ``None`` or the circuit does not contain measurements.
135
+ The final state vector as a Tensorflow tensor of shape ``(2 ** nqubits,)`` or a density matrix of shape ``(2 ** nqubits, 2 ** nqubits)``.
136
+ """
137
+ oom_error = tf .python .framework .errors_impl .ResourceExhaustedError
138
+ device = DEVICES ['DEFAULT' ]
139
+ try :
140
+ with tf .device (device ):
141
+ return self ._execute (initial_state = initial_state , nshots = nshots )
142
+ except oom_error :
143
+ raise RuntimeError (f"State does not fit in { device } memory."
144
+ "Please switch the execution device to a "
145
+ "different one using ``qibo.set_device``." )
146
+
147
+ def __call__ (self , initial_state : Optional [InitStateType ] = None ,
148
+ nshots : Optional [int ] = None ) -> OutputType :
129
149
"""Equivalent to ``circuit.execute``."""
130
150
return self .execute (initial_state = initial_state , nshots = nshots )
131
151
0 commit comments