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

Parameter table not updated after circuit assignment #6633

Open
nbronn opened this issue Jun 23, 2021 · 13 comments
Open

Parameter table not updated after circuit assignment #6633

nbronn opened this issue Jun 23, 2021 · 13 comments
Assignees
Labels
bug Something isn't working good first issue Good for newcomers help wanted community contributions welcome. For filters like http://github-help-wanted.com/

Comments

@nbronn
Copy link
Contributor

nbronn commented Jun 23, 2021

Information

  • Qiskit Terra version: 0.17.4
  • Python version: 3.9.5
  • Operating system: Darwin

What is the current behavior?

When performing a circuit assignment, _parameter_table is not updated to remove the discarded instruction, causing certain methods to fail (i.e., .copy()).

Steps to reproduce the problem

from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit import Parameter

theta = Parameter('$\\theta$')
qr = QuantumRegister(2, 'q')
qc = QuantumCircuit(qr)
qc.rz(theta, 1)
print(qc)
print(qc._parameter_table[theta])

prints

q_0: ────────────────
     ┌──────────────┐
q_1: ┤ RZ($\theta$) ├
     └──────────────┘
[(<qiskit.circuit.library.standard_gates.rz.RZGate object at 0x7ffc7bd23eb0>, 0)]

Now, modify circuit by assignment in some way, for example by adding a control to the RZGate:

# make every gate controlled by q_0
for idx, (instr, qargs, cargs) in enumerate(qc.data):
    g = instr.control(1)
    qc.data[idx] = (g, [qr[0]] + qargs, cargs)

print(qc)
print(qc._parameter_table[theta])

prints

q_0: ───────■────────
     ┌──────┴───────┐
q_1: ┤ RZ($\theta$) ├
     └──────────────┘
[(<qiskit.circuit.library.standard_gates.rz.RZGate object at 0x7ffc7bd23eb0>, 0), (<qiskit.circuit.library.standard_gates.rz.CRZGate object at 0x7ffc7bd3e370>, 0)]

Note that there are two instructions in the parameter table, one corresponding to CRZGate that was assigned, and the original RZGate that is no longer in the circuit. This causes errors when trying to map between parameter tables, for example the .copy() method:

print('Original RZ instruction id is '+str(id(qc._parameter_table[theta][0][0])))
qc.copy()

prints

Original RZ instruction id is 140722385862320
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-4-79e10aadd73c> in <module>
      1 print('Original RZ instruction id is '+str(id(qc._parameter_table[theta][0][0])))
----> 2 qc.copy()

~/anaconda3/envs/qiskit27/lib/python3.9/site-packages/qiskit/circuit/quantumcircuit.py in copy(self, name)
   1749                         for id_, instr in instr_instances.items()}
   1750 
-> 1751         cpy._parameter_table = ParameterTable({
   1752             param: [(instr_copies[id(instr)], param_index)
   1753                     for instr, param_index in self._parameter_table[param]]

~/anaconda3/envs/qiskit27/lib/python3.9/site-packages/qiskit/circuit/quantumcircuit.py in <dictcomp>(.0)
   1750 
   1751         cpy._parameter_table = ParameterTable({
-> 1752             param: [(instr_copies[id(instr)], param_index)
   1753                     for instr, param_index in self._parameter_table[param]]
   1754             for param in self._parameter_table

~/anaconda3/envs/qiskit27/lib/python3.9/site-packages/qiskit/circuit/quantumcircuit.py in <listcomp>(.0)
   1750 
   1751         cpy._parameter_table = ParameterTable({
-> 1752             param: [(instr_copies[id(instr)], param_index)
   1753                     for instr, param_index in self._parameter_table[param]]
   1754             for param in self._parameter_table

KeyError: 140722385862320

In this case, we see that the error was caused by instruction 140722385862320, which corresponds to the original RZGate instruction.

What is the expected behavior?

The parameter table should be updated upon assignment.

Suggested solutions

Remove overwritten instructions from the parameter table.

@nbronn nbronn added the bug Something isn't working label Jun 23, 2021
@Cryoris
Copy link
Contributor

Cryoris commented Jun 24, 2021

Thanks for the report! I believe we had similar issues with append/compose but fixed them there as they are the primary methods for modifying the circuit.

@kdk Since the data attribute is used a lot internally (e.g. to append) do you have an idea of whether adding a parameter table update here could have a performance impact? If no it might be good that we add a safeguard, otherwise we should maybe just clearly state that it doesn't handle the parameters properly 🤔

@kdk
Copy link
Member

kdk commented Jun 25, 2021

@kdk Since the data attribute is used a lot internally (e.g. to append) do you have an idea of whether adding a parameter table update here could have a performance impact? If no it might be good that we add a safeguard, otherwise we should maybe just clearly state that it doesn't handle the parameters properly 🤔

The fix here shouldn't have a substantial performance impact. All of our existing tooling (append,compose) should be updating the circuit through QuantumCircuit._data and manually handling ParameterTable updates. The bug here is with the validation we automatically do for setting/adding instructions through QuantumCircuit.data (without the _).

In https://github.com/Qiskit/qiskit-terra/blob/2eee566/qiskit/circuit/quantumcircuitdata.py#L59 , we already update the ParameterTable to account for the incoming instructions, but neglect to remove ParameterTable entries for the replaced instructions, which I think is the source of this bug.

(It would be good if at the same time we can update .insert to likewise update the ParameterTable.)

@kdk kdk added this to the 0.19 milestone Jun 28, 2021
@kdk kdk added good first issue Good for newcomers help wanted community contributions welcome. For filters like http://github-help-wanted.com/ and removed good first issue Good for newcomers labels Oct 26, 2021
@TakahitoMotoki
Copy link

TakahitoMotoki commented Nov 24, 2021

Can I work on this problem ?
It is the first time for me to contribute to Qiskit, but I would be happy if I could try.

@javabster
Copy link
Contributor

Sure thing, assigned to you @TakahitoMotoki! Ler us know if you need any help 😄

@TakahitoMotoki
Copy link

Thank you very much ,@javabster !

@kdk kdk modified the milestone: 0.19 Nov 30, 2021
@TakahitoMotoki
Copy link

TakahitoMotoki commented Dec 5, 2021

I have one question about a code test.

According to CONTRIBUTING.md, I need to run "tox -epy310" and "tox -elint" to check soundness and style of the modified code.

However, it seems that I cannot run tox command since my laptop is Macbook Pro with ARM processor.
Though I am trying to figure out the solution, is there any alternative way for testing?

@javabster
Copy link
Contributor

Hi @TakahitoMotoki I'm not aware that ARM processors cause issues with tox. As we currently don't yet support 3.10 I'd recommend trying tox -epy39 instead. Also for linting tox -eblack should work quicker than tox -elint and automatically fixes most linting errors. If you're still facing issues could you share the error message you're getting so we can help more.

Also might be worth making sure you have tox installed 😄

@TakahitoMotoki
Copy link

TakahitoMotoki commented Dec 6, 2021

@javabster
Thank you for your kind support!
I switched python from 3.10 to 3.9, then "tox -eblack" successfully worked on my PC.

However, I still got an error when executing "tox -epy39".
I tried to build jaxlib from source, but it didn't work. (https://jax.readthedocs.io/en/latest/developer.html)

Followings are error messages.
Thank you again for your kind support.

python version: 3.9.7
Processor: Apple M1


RuntimeError: This version of jaxlib was built using AVX instructions, which your CPU and/or operating system do not support. You may be able work around this issue by building jaxlib from source.

================================================================================
The above traceback was encountered during test discovery which imports all the found test modules in the specified test_path.
ERROR: InvocationError for command /Users/takahitomotoki/Qiskit/Dev/qiskit-terra/.tox/py39/bin/stestr run (exited with code 100)
______________________________________________________________________________________ summary ______________________________________________________________________________________
ERROR: py39: commands failed

@javabster
Copy link
Contributor

ok so this looks like an issue with jax not tox. It seems others have had the same issue, you could try some of the solutions people have mentioned here: jax-ml/jax#5501

@TakahitoMotoki
Copy link

@javabster
Thank you!

@TakahitoMotoki
Copy link

@javabster I could solve the jax problem above (I could pass the tox test!) and finally created a pull request. I am really grateful for your help.

@javabster javabster moved this to Assigned in Contributor Monitoring Jun 21, 2022
@javabster javabster moved this from Assigned to PR Open in Contributor Monitoring Jun 21, 2022
@javabster javabster moved this from PR open / Contributor working on it to Waiting for maintainer response in Contributor Monitoring Aug 1, 2022
@javabster javabster moved this from Waiting for maintainer response to Contributor MIA in Contributor Monitoring Aug 1, 2022
@HuangJunye HuangJunye moved this from Contributor MIA to PR open / Contributor working on it in Contributor Monitoring Aug 18, 2022
@javabster javabster moved this from PR open / Contributor working on it to Contributor MIA in Contributor Monitoring Sep 12, 2022
@Goldslate
Copy link

Could I please try and fix the code? I am a newbie but I would like to try and learn.

@Goldslate
Copy link

Goldslate commented Oct 30, 2022

I don't know if this will reach anyone on here but I think it was an issue of control and target.
Here's the code I wrote and please help me if it's wrong (which, I'm positive, it is)

Code:
from qiskit import *
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit import Parameter

theta = Parameter('$\theta$')
qr = QuantumRegister(2, 'q')
qc = QuantumCircuit(qr)
qc.rz(theta, 1)
qc.rz(0, 1)
print(qc)
print(qc._parameter_table[theta])

for idx, (instr, qargs, cargs) in enumerate(qc.data):
g = instr.control(1)
qc.data[idx] = (g, [qr[0]] + qargs, cargs)

print(qc)
print(qc._parameter_table[theta])

%matplotlib inline
qc.draw(output = 'mpl')

P.S. The only thing I added here was the 8th line and the mpl plot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers help wanted community contributions welcome. For filters like http://github-help-wanted.com/
Projects
Status: Contributor MIA
Development

Successfully merging a pull request may close this issue.

6 participants