Skip to content
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

Add support for parameterized qobj #485

Merged

Conversation

chriseclectic
Copy link
Member

@chriseclectic chriseclectic commented Dec 6, 2019

Summary

Allows specifying a parameterized qobj which will be expanded into multiple circuits when loading the qobj JSON.

Details and comments

qobj paramterizations are specified in the QobjConfig as

"parameterizations": [exp_0_params, ... ]

where exp_k_params = [[[i, j], [val_0, val_1, ....]], ...]
where i is the instruction position in the k qobj circuit, j is the param position for that instruction, and val_n is the value of the n-th parameterization.

For a given exp_param each parameterization instruction must have the same number of parameterization value, however the number of parameterizations can be different for each circuit in the qobj.

If non-empty the length of "parameterizations" must match the number of experiments in the qobj or an invalid qobj exception will be raised (if one of the circuits shouldn't be parameterized then it's exp_k_params should be set to an empty list []).

Example

import numpy as np
from qiskit import *

sim = Aer.get_backend("qasm_simulator")
n_params0 = 5
n_params1 = 10
parameterizations = [
    [[[0, 0], np.linspace(0, 2*np.pi, n_params0)]],
    [[[1, 2], np.linspace(0, 2*np.pi, n_params1)]]
]

qc1 = QuantumCircuit(1, 1)
qc1.ry(1, 0)
qc1.measure(0, 0)

qc2 = QuantumCircuit(2, 2)
qc2.h(1)
qc2.u1(1, 1)
qc2.h(1)
qc2.measure([0, 1], [0, 1])

qobj = assemble(transpile([qc1, qc2], basis_gates=['h', 'u3'],optimization_level=0),
               parameterizations=parameterizations)
result = sim.run(qobj).result()

print('Status: {}'.format(result.status))
print("Results for parameterized circuit 0:")
for j in range(n_params0):
    print(result.get_counts(j))

print("Results for parameterized circuit 0:")
for j in range(n_params0, n_params0 + n_params1):
    print(result.get_counts(j))

returns

Status: COMPLETED
Results for parameterized circuit 0:
{'0': 1024}
{'0': 502, '1': 522}
{'1': 1024}
{'0': 502, '1': 522}
{'0': 1024}
Results for parameterized circuit 0:
{'00': 1024}
{'10': 111, '00': 913}
{'10': 412, '00': 612}
{'10': 755, '00': 269}
{'10': 990, '00': 34}
{'10': 990, '00': 34}
{'10': 755, '00': 269}
{'10': 412, '00': 612}
{'10': 111, '00': 913}
{'00': 1024}

@chriseclectic chriseclectic requested a review from atilag as a code owner December 6, 2019 23:06
@chriseclectic chriseclectic added the on hold Can not fix yet label Jan 22, 2020
@chriseclectic chriseclectic requested a review from kdk March 9, 2020 16:24
const size_t num_instr = circuit.ops.size();
for (size_t j=0; j<num_params; j++) {
// Make a copy of the initial circuit
Circuit param_circuit = circuit;
Copy link

@ghost ghost Mar 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to copy the circuit here? You create circuit, and then in the case that there are params, you copy the circuit, edit that copy, and then push the copy and throw out the original - why not just edit the original?
Yes you need to copy it - you could still use reserve, emplace_back, and in-place editing of the circuits in circuits but perhaps there's not much difference

// So that results aren't correlated between experiments
if (seed >= 0) {
const size_t num_circs = circs.size();

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

circuits.reserve(num_circs)

Copy link
Member

@kdk kdk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a given exp_param each parameterization instruction must have the same number of parameterization value, however the number of parameterizations can be different for each circuit in the qobj.

Not an issue, just pointing out that this is different than the current Terra API which limits all circuits in a job to run under the same parameterizations.

qobj = assemble(transpile([qc1, qc2], basis_gates=['h', 'u3'],optimization_level=0),
               parameterizations=parameterizations)

There's an issue here in indexing parameterizations based on circuit gate order. There's no guarantee (even at optimization_level=0) that gates will be in the same order when the are listed in the qobj. (Using 0 as a filler param makes this somewhat more problematic, in that if param substitutions happen on the wrong gate, the circuit will likely still be executable.)

parameterizations = [
    [[[0, 0], np.linspace(0, 2*np.pi, n_params0)]],
    [[[1, 2], np.linspace(0, 2*np.pi, n_params1)]]
]

Is there an extra set of [] in the example here?

throw std::invalid_argument(R"(Invalid parameterized qobj: parameterization value out of range)");
}
// Update the param
op.params[param_pos] = params.second[j];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does the typing work here? Do we only allow a single parameter type? Or am I missing some clever templating?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment this only works for complex or double params (basically u1, u2, u3 gates).

@chriseclectic
Copy link
Member Author

@kdk It looks like an extra set of brackets because there is only 1 parameterized instruction in each of the example circuits.

Also yes, it is sensitive to order in the assembled qobj and assumes whomever made the parameterization configuration knew the index of each instruction in the qobj experiments lists.

As you say, even with optimization level zero there is no guarantee this will be the same order as circuits (Maybe if you call assemble on the circuit without any transpiling you can guarantee this though?)

@kdk
Copy link
Member

kdk commented Mar 10, 2020

As you say, even with optimization level zero there is no guarantee this will be the same order as circuits (Maybe if you call assemble on the circuit without any transpiling you can guarantee this though?)

This will be true as long as there aren't any classical conditionals (which would add instructions for the qasm to qobj conditional bfunc conversion: https://github.com/Qiskit/qiskit-terra/blob/2ee7a3a/qiskit/assembler/assemble_circuits.py#L121 ).

@chriseclectic chriseclectic force-pushed the feature/parameterized-qobj branch from 0de1317 to a361eb1 Compare March 12, 2020 15:14
@chriseclectic chriseclectic changed the title [WIP] Add support for parameterized qobj Add support for parameterized qobj Mar 12, 2020
@chriseclectic chriseclectic added this to the Aer 0.4.2 milestone Mar 31, 2020
@chriseclectic chriseclectic removed the on hold Can not fix yet label Mar 31, 2020
@chriseclectic chriseclectic force-pushed the feature/parameterized-qobj branch from d1caf3d to e494d2c Compare April 7, 2020 14:59
@chriseclectic chriseclectic merged commit 870d163 into Qiskit:master Apr 7, 2020
hhorii pushed a commit to hhorii/qiskit-aer that referenced this pull request Apr 9, 2020
* Add support for parameterized qobj

* Add Parameterized Qobj tests

Co-authored-by: Donny Greenberg <dongreenberg2@gmail.com>
mtreinish pushed a commit to mtreinish/qiskit-aer that referenced this pull request Apr 9, 2020
* Add support for parameterized qobj

* Add Parameterized Qobj tests

Co-authored-by: Donny Greenberg <dongreenberg2@gmail.com>
(cherry picked from commit 870d163)
@mtreinish mtreinish added the Changelog: Bugfix Include in the Fixed section of the changelog label Apr 9, 2020
@chriseclectic chriseclectic deleted the feature/parameterized-qobj branch April 28, 2020 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: Bugfix Include in the Fixed section of the changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants