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 an assert method testing the equality of two counts #211

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

junnaka51
Copy link
Contributor

@junnaka51 junnaka51 commented Aug 26, 2023

Summary

This PR intends to add a new assert method assert_equivalent_counts(counts_a, counts_b) testing the equality of the two counts.

Example

In [1]: from qiskit import QuantumCircuit, Aer
   ...: from quantestpy import assert_equivalent_counts
   ...: 
   ...: qc_a = QuantumCircuit(2, 2)
   ...: qc_a.h(0)
   ...: qc_a.cx(0, 1)
   ...: qc_a.measure([0, 1], [0, 1])
   ...: 
   ...: qc_b = QuantumCircuit(2, 2)
   ...: qc_b.h(0)
   ...: qc_b.h(1)
   ...: qc_b.cz(0, 1)
   ...: qc_b.h(1)
   ...: qc_b.measure([0, 1], [0, 1])
   ...: 
   ...: simulator = Aer.get_backend('qasm_simulator')
   ...: counts_a = simulator.run(qc_a).result().get_counts()
   ...: counts_b = simulator.run(qc_b).result().get_counts() 

In [2]: counts_a
Out[2]: {'00': 491, '11': 533}

In [3]: counts_b
Out[3]: {'00': 514, '11': 510}

In [4]: assert_equivalent_counts(counts_a, counts_b)

In [5]: assert_equivalent_counts(counts_a, counts_b, 0.5)
---------------------------------------------------------------------------
QuantestPyAssertionError                  Traceback (most recent call last)
Cell In[5], line 1
----> 1 assert_equivalent_counts(counts_a, counts_b, 0.5)

File /mnt/workspace/quantestpy_fork/quantestpy/assertion/assert_equivalent_counts.py:74, in assert_equivalent_counts(counts_a, counts_b, sigma, msg)
     70         err_msg = f"The values of key {k} are too different.\n" \
     71             f"counts_a[{k}] = {v_a}, counts_b[{k}] = {v_b}.\n" \
     72             f"Difference: {diff}\nTolerance: {int(tole)}."
     73         msg = ut_test_case._formatMessage(msg, err_msg)
---> 74         raise QuantestPyAssertionError(msg)
     76 else:
     77     err_msg = f"The key {k} in counts_a is not in counts_b."

QuantestPyAssertionError: The values of key 00 are too different.
counts_a[00] = 491, counts_b[00] = 514.
Difference: 23
Tolerance: 22.

@@ -67,6 +67,9 @@ def test_rz(self,):
# qiskit.mcrz is multi-controlled Z rotation up to a global phase,
# which means that qiskit.mcrz coincides with multi-controlled p gate.
# (Namely, qiskit.mcrz is same as qiskit.mcp.)
@unittest.skip(
"This test fails due most likely to a version update of qiskit."
)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test is skipped since it fails due most likely to a version update of Qiskit:

======================================================================
FAIL: test_mcrz (simulator.state_vector_circuit.test_rz_gate.TestStateVectorCircuitRyGate)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/runner/work/quantestpy/quantestpy/test/with_qiskit/simulator/state_vector_circuit/test_rz_gate.py", line 75, in test_mcrz
    qpc = cvt_input_circuit_to_quantestpy_circuit(qc)
  File "/home/runner/work/quantestpy/quantestpy/quantestpy/converter/converter_to_quantestpy_circuit.py", line 23, in cvt_input_circuit_to_quantestpy_circuit
    quantestpy_circuit = _cvt_qiskit_to_quantestpy_circuit(circuit)
  File "/home/runner/work/quantestpy/quantestpy/quantestpy/converter/sdk/qiskit.py", line 365, in _cvt_qiskit_to_quantestpy_circuit
    raise QuantestPyError(
quantestpy.exceptions.QuantestPyError: Qiskit gate [unitary] is not supported in QuantestPy.
Implemented qiskit gates: ['ccx', 'ccz', 'ch', 'cp', 'crx', 'cry', 'crz', 'cs', 'csdg', 'cswap', 'csx', 'cu', 'cx', 'cy', 'cz', 'h', 'id', 'iswap', 'mcp', 'mcx', 'p', 'r', 'rx', 'ry', 'rz', 's', 'sdg', 'swap', 'sx', 'sxdg', 't', 'tdg', 'u', 'x', 'y', 'z']

----------------------------------------------------------------------

Copy link
Contributor

@mitz1012 mitz1012 left a comment

Choose a reason for hiding this comment

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

@junnaka51
Thank you for your contribution!
But I have a question about the definition of "tole".
Please check my inline comments.

)
)

def test_approx_equivalent(self,):
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did not test_approx_equivalent give an error?
I think your definition of "tole" gives an error when key = "00":

abs(100-80) > sqrt(100) + sqrt(80)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is because the default value to sigma is 2, and the following is satisfied:

abs(100-80) < 2 * (sqrt(100) + sqrt(80))

err_b = np.sqrt(v_b)

diff = np.abs(v_a - v_b)
tole = (err_a + err_b) * sigma
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you define it this way?
I think this definition is unsuitable because the dimension of 'diff' is different from that of 'tole'.
Of course, count has no dimension in this case, but please image the case when the dimension of v_a is length(cm).

If there are a lot of data, we may use Root Sum Squire as the definition of 'tole'.
But I don't know an appropriate definition when we compare two values...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is assumed that counts_a[key] and counts_b[key] are always the number of times each bitstring key was measured. I believe that users can understand it from the document doc/assertion/assert_equivalent_counts.md.

The standard deviation for the number of times measured N is sqrt(N), therefore the definition of tole should be okay. Another possibility may be

tole = sqrt(v_a + v_b) * sigma

It is fine for me to define the both and leave users to decide which one they use?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants