-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make it easier to assign parameters to vector of parameters #5557
Comments
If you do qc.bind_parameters(qc.ordered_parameters: np.random.random(15)} I think that should work. But yeah I agree it's cumbersome (especially bc that |
Yeah, so it does seem that some circuits in the circuit library accept arrays as inputs to |
Hi. I created this quick patch for addressing this enhancement request. diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py
index 5ef05744..0e435d3d 100644
--- a/qiskit/circuit/quantumcircuit.py
+++ b/qiskit/circuit/quantumcircuit.py
@@ -2035,7 +2035,29 @@ class QuantumCircuit:
"""
if any(isinstance(value, ParameterExpression) for value in value_dict.values()):
raise TypeError('Found ParameterExpression in values; use assign_parameters() instead.')
- return self.assign_parameters(value_dict)
+ parsed_value_dict = {}
+ # allow for key,value pair types other than Parameter(),value in the value_dict
+ # so that parameter vectors can be assigned easily
+ for the_param_key in value_dict.keys():
+ param_name = ''
+ # handle 'str,array()' pair type where str is the name of the vector
+ if isinstance(the_param_key, str):
+ param_name = the_param_key
+ # handle 'ParameterVector(),array()' pair type
+ elif isinstance(the_param_key, ParameterVector):
+ param_name = the_param_key.name
+ # if param_name is set then parse value dict
+ if param_name:
+ the_values = value_dict[the_param_key]
+ for i in range(len(the_values)):
+ print(i)
+ for key in self.parameters:
+ if key.name == '{}[{}]'.format(param_name, i):
+ parsed_value_dict[key] = the_values[i]
+ # otherwise just copy the item
+ else:
+ parsed_value_dict[the_param_key] = value_dict[the_param_key]
+ return self.assign_parameters(parsed_value_dict)
def _unroll_param_dict(self, value_dict):
unrolled_value_dict = {} It seems to work on the proposed scenario. Let me know if this would be a viable code change and I'll be happy to work on a PR. |
I agree that we should enhance assigning parameters to circuits, right now it can be quite cumbersome. But I think we should properly discuss how we want to do that, such that we don't end up with too many different possibilities. The simplest manner to assign an array of values, in my opinion would just be # ``circuit`` contains some parameters
values = [0, 1, 2]
bound_circuit = circuit.assign_parameters(values) This would be very convenient for usage with optimizers and optimization algorithms in Qiskit, such as the VQE. If you want to only bind certain parameters, we could use the current scheme partially_bound = circuit.assign_parameters({x: value}) Personally I'd be fine if that'd work with a string as well, since parameter names are unique in circuits. partially_bound = circuit.assign_parameters({'x': value}) The first 'anonymous' assign to just an array requires a notion of parameter order. We don't have that at the moment but we're working on this with @ewinston 🙂 So I think the following would cover @nonhermitian cases and would be very user-friendly to go forward:
We could split this in two PRs and add assign per name now and the array-assign later. But we should get more opinions on if this could break some things, e.g. from @kdk |
Thanks @paolob67 , this looks like a good approach. Can you open a PR and we can discuss it further there? |
Yes no prob. I'll work on adding a couple of test cases and then I'll create a PR. Thanks. |
What is the expected enhancement?
It is currently a struggle to figure out how to bind a vector of parameters to a circuit. There is no example in the tutorials for doing this (that I could find) and the only example that I could make work is the following:
However this is confusing because one is temped to do either
qc.bind_parameters({'th': np.random.random(15)})
orqc.bind_parameters({ParameterVector('th', 15): np.random.random(15)})
, both of which do not work. Moreover, inputting any key value one wants does not raise an exception, which makes things even more difficult to debug.Finally the returned parameters in
qc.parameters
are not in numeric order that also makes things a mess, e.g."The text was updated successfully, but these errors were encountered: