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

Issue 6633: Update _parameter_table after circuit assignment #7434

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
ace8f24
Update _parameter_table after circuit assignment
TakahitoMotoki Dec 5, 2021
471f1aa
Update _parameter_table after circuit assignment
TakahitoMotoki Dec 14, 2021
da1a64f
Update _parameter_table after circuit assignment
TakahitoMotoki Dec 20, 2021
68b157b
Update _parameter_table after circuit assignment
TakahitoMotoki Dec 22, 2021
a540ec1
Merge branch 'main' into issue_6633
TakahitoMotoki Dec 22, 2021
4551c3d
Merge branch 'main' into issue_6633
TakahitoMotoki Dec 22, 2021
b50f8a8
Update _parameter_table after circuit assignment
TakahitoMotoki Dec 30, 2021
f5be2ad
Merge branch 'main' into issue_6633
TakahitoMotoki Dec 30, 2021
5c9ff04
Update _parameter_table after circuit assignment
TakahitoMotoki Dec 30, 2021
05a13a5
Merge branch 'issue_6633' of https://github.com/TakahitoMotoki/qiskit…
TakahitoMotoki Dec 30, 2021
ed4395e
Merge branch 'main' into issue_6633
TakahitoMotoki Jan 5, 2022
d318a18
Update _parameter_table after circuit assignment
TakahitoMotoki Jan 5, 2022
1db7729
Update _parameter_table after circuit assignment
TakahitoMotoki Jan 5, 2022
b2837b1
Merge branch 'main' into issue_6633
TakahitoMotoki Jan 14, 2022
e16f51c
Add a test to test_circuit_data.py
TakahitoMotoki Jan 14, 2022
e8e54a9
Add a release note
TakahitoMotoki Jan 14, 2022
b5969ad
Merge branch 'main' into issue_6633
TakahitoMotoki Feb 2, 2022
3c352cc
Add public function to ParameterTable.py
TakahitoMotoki Feb 3, 2022
86dc448
Update tox -eblack
TakahitoMotoki Feb 6, 2022
9592520
Modify test case
TakahitoMotoki Feb 10, 2022
2832122
run tox -eblack
TakahitoMotoki Feb 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions qiskit/circuit/parametertable.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from collections.abc import MutableMapping, MappingView

from .instruction import Instruction
from .parameter import Parameter


class ParameterTable(MutableMapping):
Expand Down Expand Up @@ -52,6 +53,13 @@ def __setitem__(self, parameter, instr_params):
self._keys.add(parameter)
self._names.add(parameter.name)

def delete_element(self, instruction: Instruction):
for param_index, param in enumerate(instruction.params):
if isinstance(param, Parameter):
for idx, spec in enumerate(self._table[param]):
if spec[0] is instruction and spec[1] == param_index:
self._table[param].pop(idx)

def get_keys(self):
"""Return a set of all keys in the parameter table

Expand Down
4 changes: 4 additions & 0 deletions qiskit/circuit/quantumcircuitdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ def __setitem__(self, key, value):
self._circuit._check_qargs(qargs)
self._circuit._check_cargs(cargs)

if isinstance(self._circuit._data[key], tuple):
old_instruction = self._circuit._data[key][0]
self._circuit._parameter_table.delete_element(old_instruction)

self._circuit._data[key] = (instruction, qargs, cargs)

self._circuit._update_parameter_table(instruction)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fixes:
- |
Fixed a bug when ``QuantumCircuit._parameter_table`` is inconsistent with
``QuantumCircuit.data`` after a circuit assignment.
In __setitem__ of QuantumCiruitData, for each new entry, the old element
is removed and the new element is added properly.
67 changes: 66 additions & 1 deletion test/python/circuit/test_circuit_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"""Test operations on circuit.data."""

from qiskit.circuit import QuantumCircuit, QuantumRegister, Parameter
from qiskit.circuit.library import HGate, XGate, CXGate, RXGate
from qiskit.circuit.library import HGate, XGate, CXGate, RXGate, UGate

from qiskit.test import QiskitTestCase
from qiskit.circuit.exceptions import CircuitError
Expand Down Expand Up @@ -425,3 +425,68 @@ def test_param_gate_instance(self):
qc0_instance = qc0._parameter_table[b][0][0]
qc1_instance = qc1._parameter_table[a][0][0]
self.assertNotEqual(qc0_instance, qc1_instance)

def test_parameter_table_is_updated(self):
"""
Verify that qc._parameter_table is consistent with qc.data when qc.data is updated with __setitem__ in quantumcircuitdata.py

- Case1-1. Add an instruction with a parameter that was not previously in ParameterTable.
- Case1-2. Add an instrcution with a parameter that was in ParameterTable.

- Case2-1. Replace an instruction with a parameter by other instruction with the same parameter.
- Case2-2. Replace an instruction with a parameter by other instruction with a different parameter.
- Case2-3. Replace an instruction with a parameter by other instruction with no parameter.

- Case3-1. Add an instruction with multiple parameter
- Case3-2. Replace an instruction with multiple parameter by other instruction

"""
qr = QuantumRegister(3, "q")
qc = QuantumCircuit(qr)
qc_case1 = qc.copy()
qc_case2 = qc.copy()
qc_case3 = qc.copy()

# Case1-1, 1-2
param1 = Parameter("param1")
qc.rx(param1, 0) # Case1-1
qc.rx(param1, 0) # Case1-2
qc.rx(param1, 0)

# Create an expected ParaemterTable for Case1-1, 1-2
qc_case1._parameter_table[param1] = [(qc.data[0][0], 0)]
qc_case1._parameter_table[param1].append((qc.data[1][0], 0))
qc_case1._parameter_table[param1].append((qc.data[2][0], 0))

# Assertion for Case1-1, 1-2
self.assertEqual(qc._parameter_table, qc_case1._parameter_table)

# Case2-1, 2-2, 2-3
param2 = Parameter("param2")
qc.data[0] = (RXGate(param1), [qr[0]], []) # Case2-1
qc.data[1] = (RXGate(param2), [qr[0]], []) # Case2-2
qc.data[2] = (HGate(), [qr[0]], []) # Case2-3

# Create an expected ParaemterTable for Case2-1, 2-2, 2-3
qc_case2._parameter_table[param1] = [(qc.data[0][0], 0)]
qc_case2._parameter_table[param2] = [(qc.data[1][0], 0)]

# Assertion for Case2-1, 2-2, 2-3
self.assertEqual(qc._parameter_table, qc_case2._parameter_table)

# Case3-1, 3-2
param3 = Parameter("param3")
qc.u(param1, param2, param3, 0) # Case3-1
qc.u(param1, param2, param3, 0)
qc.data[4] = (RXGate(param1), [qr[0]], []) # Case3-2

# Create an expected ParaemterTable for Case3-1, 3-2
qc_case3._parameter_table[param1] = [(qc.data[0][0], 0)]
qc_case3._parameter_table[param2] = [(qc.data[1][0], 0)]
qc_case3._parameter_table[param1].append((qc.data[3][0], 0))
qc_case3._parameter_table[param2].append((qc.data[3][0], 1))
qc_case3._parameter_table[param3] = [(qc.data[3][0], 2)]
qc_case3._parameter_table[param1].append((qc.data[4][0], 0))

# Assertion for Case3-1, 3-2
self.assertEqual(qc._parameter_table, qc_case3._parameter_table)