Thank you for all the help and the thoughtful response!
When I naively put the similar cost function you described above into my opt.step I get an error. Here’s my code:
def cost(params, phi):
return np.mean(circuit(params, phi))
L = 1
init_params = create_params(L)
phi = phi = np.array([0.001], requires_grad=False)
nqubits = 10
eta = 0.01
steps = 200
opt = qml.QNGOptimizer(eta)
qng_cost = []
for _ in range(steps):
print(f'Step: {_}')
new_params = opt.step(cost, init_params, phi)
qng_cost.append(circuit(new_params))
Here’s the error:
{
"name": "ValueError",
"message": "The objective function must either be encoded as a single QNode or an ExpvalCost object for the natural gradient to be automatically computed. Otherwise, metric_tensor_fn must be explicitly provided to the optimizer.",
"stack": "---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
for _ in range(steps):
print(f'Step: {_}')
---> new_params = opt.step(cost, init_params, phi)
qng_cost.append(circuit(new_params))
File ~/..., in QNGOptimizer.step(self, qnode, grad_fn, recompute_tensor, metric_tensor_fn, *args, **kwargs)
229 def step(
230 self, qnode, *args, grad_fn=None, recompute_tensor=True, metric_tensor_fn=None, **kwargs
231 ):
232 \"\"\"Update the parameter array :math:`x` with one step of the optimizer.
233
234 Args:
(...)
251 array: the new variable values :math:`x^{(t+1)}`
252 \"\"\"
--> 253 new_args, _ = self.step_and_cost(
254 qnode,
255 *args,
256 grad_fn=grad_fn,
257 recompute_tensor=recompute_tensor,
258 metric_tensor_fn=metric_tensor_fn,
259 **kwargs,
260 )
261 return new_args
File ~..., in QNGOptimizer.step_and_cost(self, qnode, grad_fn, recompute_tensor, metric_tensor_fn, *args, **kwargs)
180 # pylint: disable=arguments-differ
181 if not isinstance(qnode, (qml.QNode, qml.ExpvalCost)) and metric_tensor_fn is None:
--> 182 raise ValueError(
183 \"The objective function must either be encoded as a single QNode or \"
184 \"an ExpvalCost object for the natural gradient to be automatically computed. \"
185 \"Otherwise, metric_tensor_fn must be explicitly provided to the optimizer.\"
186 )
188 if recompute_tensor or self.metric_tensor is None:
189 if metric_tensor_fn is None:
ValueError: The objective function must either be encoded as a single QNode or an ExpvalCost object for the natural gradient to be automatically computed. Otherwise, metric_tensor_fn must be explicitly provided to the optimizer."
}
Now, when I read the documentation here for the QNGOptimizer
, I updated my opt.step()
to include the metric_tensor_fn
argument with the cost
function:
for _ in range(steps):
print(f'Step: {_}')
new_params = opt.step(circuit, init_params, phi, metric_tensor_fn=cost)
qng_cost.append(circuit(new_params))
but now I get this error:
{
"name": "TypeError",
"message": "'numpy.float64' object cannot be interpreted as an integer",
"stack": "---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
File ~..., in _wrapfunc(obj, method, *args, **kwds)
58 try:
---> 59 return bound(*args, **kwds)
60 except TypeError:
61 # A TypeError occurs if the object does have such a method in its
62 # class, but its signature is not identical to that of NumPy's. This
(...)
66 # Call _wrapit from within the except clause to ensure a potential
67 # exception has a traceback chain.
TypeError: 'numpy.float64' object cannot be interpreted as an integer
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
/... Cell 13 line 1
for _ in range(steps):
print(f'Step: {_}')
---> new_params = opt.step(circuit, init_params, phi, metric_tensor_fn=cost)
qng_cost.append(circuit(new_params))
File ~/..., in QNGOptimizer.step(self, qnode, grad_fn, recompute_tensor, metric_tensor_fn, *args, **kwargs)
229 def step(
230 self, qnode, *args, grad_fn=None, recompute_tensor=True, metric_tensor_fn=None, **kwargs
231 ):
232 \"\"\"Update the parameter array :math:`x` with one step of the optimizer.
233
234 Args:
(...)
251 array: the new variable values :math:`x^{(t+1)}`
252 \"\"\"
--> 253 new_args, _ = self.step_and_cost(
254 qnode,
255 *args,
256 grad_fn=grad_fn,
257 recompute_tensor=recompute_tensor,
258 metric_tensor_fn=metric_tensor_fn,
259 **kwargs,
260 )
261 return new_args
File ~/..., in QNGOptimizer.step_and_cost(self, qnode, grad_fn, recompute_tensor, metric_tensor_fn, *args, **kwargs)
194 shape = qml.math.shape(_metric_tensor)
195 size = qml.math.prod(shape[: len(shape) // 2])
--> 196 self.metric_tensor = qml.math.reshape(_metric_tensor, (size, size))
197 # Add regularization
198 self.metric_tensor = self.metric_tensor + self.lam * qml.math.eye(
199 size, like=_metric_tensor
200 )
File ~/..., in do(fn, like, *args, **kwargs)
31 \"\"\"Do function named ``fn`` on ``(*args, **kwargs)``, peforming single
32 dispatch to retrieve ``fn`` based on whichever library defines the class of
33 the ``args[0]``, or the ``like`` keyword argument if specified.
(...)
77 <tf.Tensor: id=91, shape=(3, 3), dtype=float32>
78 \"\"\"
79 backend = choose_backend(fn, *args, like=like, **kwargs)
---> 80 return get_lib_fn(backend, fn)(*args, **kwargs)
File ~/..., in reshape(a, newshape, order)
200 @array_function_dispatch(_reshape_dispatcher)
201 def reshape(a, newshape, order='C'):
202 \"\"\"
203 Gives a new shape to an array without changing its data.
204
(...)
283 [5, 6]])
284 \"\"\"
--> 285 return _wrapfunc(a, 'reshape', newshape, order=order)
File ~/..., in _wrapfunc(obj, method, *args, **kwds)
59 return bound(*args, **kwds)
60 except TypeError:
61 # A TypeError occurs if the object does have such a method in its
62 # class, but its signature is not identical to that of NumPy's. This
(...)
66 # Call _wrapit from within the except clause to ensure a potential
67 # exception has a traceback chain.
---> 68 return _wrapit(obj, method, *args, **kwds)
File ~/..., in _wrapit(obj, method, *args, **kwds)
43 except AttributeError:
44 wrap = None
---> 45 result = getattr(asarray(obj), method)(*args, **kwds)
46 if wrap:
47 if not isinstance(result, mu.ndarray):
TypeError: 'numpy.float64' object cannot be interpreted as an integer"
}
I’m unsure what’s going on here. Also, I want to point out that the phi
parameter of my circuit is just a parameter with requires_grad=False
. Thank you!