13
13
"""Quantum Generator."""
14
14
15
15
from typing import Optional , List , Union , Dict , Any
16
+ import warnings
16
17
from copy import deepcopy
17
18
import numpy as np
18
19
19
20
from qiskit import QuantumRegister , ClassicalRegister , QuantumCircuit
20
21
from qiskit .circuit .library import TwoLocal
21
22
from qiskit .aqua import aqua_globals
22
23
from qiskit .aqua .components .optimizers import ADAM
23
- from qiskit .aqua .components .uncertainty_models import \
24
- UniformDistribution , MultivariateUniformDistribution
25
24
from qiskit .aqua .components .uncertainty_models import UnivariateVariationalDistribution , \
26
25
MultivariateVariationalDistribution
27
- from qiskit .aqua import AquaError
28
26
from qiskit .aqua .components .neural_networks .generative_network import GenerativeNetwork
29
- from qiskit .aqua .components .initial_states import Custom
30
27
31
28
# pylint: disable=invalid-name
32
29
@@ -72,61 +69,32 @@ def __init__(self,
72
69
self ._bounds = bounds
73
70
self ._num_qubits = num_qubits
74
71
self .generator_circuit = generator_circuit
75
- if self .generator_circuit is None :
76
- entangler_map = []
77
- if np .sum (num_qubits ) > 2 :
78
- for i in range (int (np .sum (num_qubits ))):
79
- entangler_map .append ([i , int (np .mod (i + 1 , np .sum (num_qubits )))])
80
- else :
81
- if np .sum (num_qubits ) > 1 :
82
- entangler_map .append ([0 , 1 ])
83
-
84
- if len (num_qubits ) > 1 :
85
- num_qubits = list (map (int , num_qubits ))
86
- low = bounds [:, 0 ].tolist ()
87
- high = bounds [:, 1 ].tolist ()
88
- init_dist = MultivariateUniformDistribution (num_qubits , low = low , high = high )
89
- q = QuantumRegister (sum (num_qubits ))
90
- qc = QuantumCircuit (q )
91
- init_dist .build (qc , q )
92
- init_distribution = Custom (num_qubits = sum (num_qubits ), circuit = qc )
93
- # Set variational form
94
- var_form = TwoLocal (sum (num_qubits ), 'ry' , 'cz' , reps = 1 ,
95
- initial_state = init_distribution ,
96
- entanglement = entangler_map )
97
- if init_params is None :
98
- init_params = aqua_globals .random .random (var_form .num_parameters ) * 2 * 1e-2
99
- # Set generator circuit
100
- self .generator_circuit = MultivariateVariationalDistribution (num_qubits , var_form ,
101
- init_params ,
102
- low = low , high = high )
103
- else :
104
- init_dist = UniformDistribution (sum (num_qubits ), low = bounds [0 ], high = bounds [1 ])
105
- q = QuantumRegister (sum (num_qubits ), name = 'q' )
106
- qc = QuantumCircuit (q )
107
- init_dist .build (qc , q )
108
- init_distribution = Custom (num_qubits = sum (num_qubits ), circuit = qc )
109
- var_form = TwoLocal (sum (num_qubits ), 'ry' , 'cz' , reps = 1 ,
110
- initial_state = init_distribution ,
111
- entanglement = entangler_map )
112
- if init_params is None :
113
- init_params = aqua_globals .random .random (var_form .num_parameters ) * 2 * 1e-2
114
- # Set generator circuit
115
- self .generator_circuit = UnivariateVariationalDistribution (
116
- int (np .sum (num_qubits )), var_form , init_params , low = bounds [0 ], high = bounds [1 ])
117
-
118
- if len (num_qubits ) > 1 :
119
- if isinstance (self .generator_circuit , MultivariateVariationalDistribution ):
120
- pass
121
- else :
122
- raise AquaError ('Set multivariate variational distribution '
123
- 'to represent multivariate data' )
72
+ if generator_circuit is None :
73
+ circuit = QuantumCircuit (sum (num_qubits ))
74
+ circuit .h (circuit .qubits )
75
+ var_form = TwoLocal (sum (num_qubits ), 'ry' , 'cz' , reps = 1 , entanglement = 'circular' )
76
+ circuit .compose (var_form , inplace = True )
77
+
78
+ # Set generator circuit
79
+ self .generator_circuit = circuit
80
+
81
+ if isinstance (generator_circuit , (UnivariateVariationalDistribution ,
82
+ MultivariateVariationalDistribution )):
83
+ warnings .warn ('Passing a UnivariateVariationalDistribution or MultivariateVariational'
84
+ 'Distribution is as ``generator_circuit`` is deprecated as of Aqua 0.8.0 '
85
+ 'and the support will be removed no earlier than 3 months after the '
86
+ 'release data. You should pass as QuantumCircuit instead.' ,
87
+ DeprecationWarning , stacklevel = 2 )
88
+ self ._free_parameters = generator_circuit ._var_form_params
89
+ self .generator_circuit = generator_circuit ._var_form
124
90
else :
125
- if isinstance (self .generator_circuit , UnivariateVariationalDistribution ):
126
- pass
127
- else :
128
- raise AquaError ('Set univariate variational distribution '
129
- 'to represent univariate data' )
91
+ self ._free_parameters = list (self .generator_circuit .parameters )
92
+
93
+ if init_params is None :
94
+ init_params = aqua_globals .random .random (self .generator_circuit .num_parameters ) * 2e-2
95
+
96
+ self ._bound_parameters = init_params
97
+
130
98
# Set optimizer for updating the generator network
131
99
self ._optimizer = ADAM (maxiter = 1 , tol = 1e-6 , lr = 1e-3 , beta_1 = 0.7 ,
132
100
beta_2 = 0.99 , noise_factor = 1e-6 ,
@@ -192,26 +160,28 @@ def construct_circuit(self, params=None):
192
160
Construct generator circuit.
193
161
194
162
Args:
195
- params (numpy.ndarray): parameters which should be used to run the generator,
196
- if None use self._params
163
+ params (list | dict): parameters which should be used to run the generator.
197
164
198
165
Returns:
199
166
Instruction: construct the quantum circuit and return as gate
200
167
"""
201
-
202
- q = QuantumRegister (sum (self ._num_qubits ), name = 'q' )
203
- qc = QuantumCircuit (q )
204
168
if params is None :
205
- self .generator_circuit .build (qc = qc , q = q )
206
- else :
207
- generator_circuit_copy = deepcopy (self .generator_circuit )
208
- generator_circuit_copy .params = params
209
- generator_circuit_copy .build (qc = qc , q = q )
169
+ return self .generator_circuit
210
170
211
- # return qc.copy(name='qc')
212
- return qc . to_instruction ( )
171
+ if isinstance ( params , ( list , np . ndarray )):
172
+ params = dict ( zip ( self . _free_parameters , params ) )
213
173
214
- def get_output (self , quantum_instance , qc_state_in = None , params = None , shots = None ):
174
+ return self .generator_circuit .assign_parameters (params )
175
+ # self.generator_circuit.build(qc=qc, q=q)
176
+ # else:
177
+ # generator_circuit_copy = deepcopy(self.generator_circuit)
178
+ # generator_circuit_copy.params = params
179
+ # generator_circuit_copy.build(qc=qc, q=q)
180
+
181
+ # # return qc.copy(name='qc')
182
+ # return qc.to_instruction()
183
+
184
+ def get_output (self , quantum_instance , params = None , shots = None ):
215
185
"""
216
186
Get classical data samples from the generator.
217
187
Running the quantum generator circuit results in a quantum state.
@@ -222,7 +192,6 @@ def get_output(self, quantum_instance, qc_state_in=None, params=None, shots=None
222
192
Args:
223
193
quantum_instance (QuantumInstance): Quantum Instance, used to run the generator
224
194
circuit.
225
- qc_state_in (QuantumCircuit): deprecated
226
195
params (numpy.ndarray): array or None, parameters which should
227
196
be used to run the generator, if None use self._params
228
197
shots (int): if not None use a number of shots that is different from the
@@ -234,6 +203,8 @@ def get_output(self, quantum_instance, qc_state_in=None, params=None, shots=None
234
203
instance_shots = quantum_instance .run_config .shots
235
204
q = QuantumRegister (sum (self ._num_qubits ), name = 'q' )
236
205
qc = QuantumCircuit (q )
206
+ if params is None :
207
+ params = self ._bound_parameters
237
208
qc .append (self .construct_circuit (params ), q )
238
209
if quantum_instance .is_statevector :
239
210
pass
@@ -277,7 +248,7 @@ def get_output(self, quantum_instance, qc_state_in=None, params=None, shots=None
277
248
temp .append (self ._data_grid [int (bin_rep )])
278
249
generated_samples .append (temp )
279
250
280
- self .generator_circuit ._probabilities = generated_samples_weights
251
+ # self.generator_circuit._probabilities = generated_samples_weights
281
252
if shots is not None :
282
253
# Restore the initial quantum_instance configuration
283
254
quantum_instance .set_config (shots = instance_shots )
@@ -347,13 +318,13 @@ def train(self, quantum_instance=None, shots=None):
347
318
self ._optimizer ._maxiter = 1
348
319
self ._optimizer ._t = 0
349
320
objective = self ._get_objective_function (quantum_instance , self ._discriminator )
350
- self .generator_circuit . params , loss , _ = self ._optimizer .optimize (
351
- num_vars = len (self .generator_circuit . params ),
321
+ self ._bound_parameters , loss , _ = self ._optimizer .optimize (
322
+ num_vars = len (self ._bound_parameters ),
352
323
objective_function = objective ,
353
- initial_point = self .generator_circuit . params
324
+ initial_point = self ._bound_parameters
354
325
)
355
326
356
327
self ._ret ['loss' ] = loss
357
- self ._ret ['params' ] = self .generator_circuit . params
328
+ self ._ret ['params' ] = self ._bound_parameters
358
329
359
330
return self ._ret
0 commit comments