Repository: QuantestPy/quantestpy (language: python)

Issue:
Implement a function cvt_qobj_to_test_circuit(qobj: dict) -> TestCircuit

Implement a function cvt_qobj_to_test_circuit(qobj: dict) -> TestCircuit



Discussion / hints:

Fix patch:
diff --git a/.github/workflows/github-actions.yml b/.github/workflows/github-actions.yml
index 03b0882..3dbb370 100644
--- a/.github/workflows/github-actions.yml
+++ b/.github/workflows/github-actions.yml
@@ -13,9 +13,9 @@ jobs:
       - name: Setup Python3.8
         uses: actions/setup-python@v4
         with:
-          python-version: '3.8'
-          cache: 'pip'
-          cache-dependency-path: './test/requirements.txt'
+          python-version: "3.8"
+          cache: "pip"
+          cache-dependency-path: "./test/requirements.txt"
 
       - name: Install library
         run: |
@@ -32,3 +32,4 @@ jobs:
           python3 -m unittest test.test_test_circuit
           python3 -m unittest test.test_circuit_assert_equal_to_operator
           python3 -m unittest test.test_circuit_assert_is_zero
+          python3 -m unittest test.test_converter


Test patch:
diff --git a/quantestpy/circuit.py b/quantestpy/circuit.py
index b9f96db..e5da2b0 100644
--- a/quantestpy/circuit.py
+++ b/quantestpy/circuit.py
@@ -1,11 +1,14 @@
 import unittest
 import numpy as np
 from typing import Union
+from qiskit import QuantumCircuit
 
 from quantestpy import operator
 from quantestpy import TestCircuit
 from quantestpy.exceptions import QuantestPyError, QuantestPyAssertionError
-from quantestpy.test_circuit import cvt_openqasm_to_test_circuit
+from quantestpy.converter import _cvt_qiskit_to_test_circuit
+from quantestpy.converter import _cvt_openqasm_to_test_circuit
+
 
 ut_test_case = unittest.TestCase()
 
@@ -13,28 +16,31 @@
 def assert_equal_to_operator(
         operator_: Union[np.ndarray, np.matrix],
         qasm: str = None,
+        qiskit_circuit: QuantumCircuit = None,
         test_circuit: TestCircuit = None,
         from_right_to_left_for_qubit_ids: bool = False,
         number_of_decimal_places: int = 5,
         check_including_global_phase: bool = True,
         msg=None) -> None:
 
-    #
-    if qasm is None and test_circuit is None:
+    if qasm is None and qiskit_circuit is None and test_circuit is None:
         raise QuantestPyError(
-            "Missing qasm or test circuit."
+            "Missing qasm or qiskit_circuit or test circuit."
         )
 
-    if qasm is not None and test_circuit is not None:
+    if (qasm is not None and qiskit_circuit is not None) \
+            or (qasm is not None and test_circuit is not None) \
+            or (qiskit_circuit is not None and test_circuit is not None):
         raise QuantestPyError(
-            "Qasm and test circuit must not both be given."
+            "You need to choose one parameter of Qasm, \
+                qiskit_circuit and test circuit."
         )
 
     if qasm is not None:
-        test_circuit = cvt_openqasm_to_test_circuit(qasm)
-        raise QuantestPyError(
-            "Loading qasm is not yet implemented."
-        )
+        test_circuit = _cvt_openqasm_to_test_circuit(qasm)
+
+    if qiskit_circuit is not None:
+        test_circuit = _cvt_qiskit_to_test_circuit(qiskit_circuit)
 
     test_circuit._from_right_to_left_for_qubit_ids = \
         from_right_to_left_for_qubit_ids
@@ -50,6 +56,7 @@ def assert_equal_to_operator(
 
 
 def assert_is_zero(qasm: str = None,
+                   qiskit_circuit: QuantumCircuit = None,
                    test_circuit: TestCircuit = None,
                    qubits: list = None,
                    number_of_decimal_places: int = 5,
@@ -57,21 +64,24 @@ def assert_is_zero(qasm: str = None,
 
     # Memo220805JN: the following input checker may be common for the other
     # functions in this module, thus can be one function.
-    if qasm is None and test_circuit is None:
+    if qasm is None and qiskit_circuit is None and test_circuit is None:
         raise QuantestPyError(
-            "Missing qasm or test circuit."
+            "Missing qasm or qiskit_circuit or test circuit."
         )
 
-    if qasm is not None and test_circuit is not None:
+    if (qasm is not None and qiskit_circuit is not None) \
+            or (qasm is not None and test_circuit is not None) \
+            or (qiskit_circuit is not None and test_circuit is not None):
         raise QuantestPyError(
-            "Qasm and test circuit must not both be given."
+            "You need to choose one parameter of Qasm, \
+                qiskit_circuit and test circuit."
         )
 
     if qasm is not None:
-        test_circuit = cvt_openqasm_to_test_circuit(qasm)
-        raise QuantestPyError(
-            "Loading qasm is not yet implemented."
-        )
+        test_circuit = _cvt_openqasm_to_test_circuit(qasm)
+
+    if qiskit_circuit is not None:
+        test_circuit = _cvt_qiskit_to_test_circuit(qiskit_circuit)
 
     if not isinstance(qubits, list) and qubits is not None:
         raise QuantestPyError(
diff --git a/quantestpy/converter.py b/quantestpy/converter.py
new file mode 100644
index 0000000..94e911a
--- /dev/null
+++ b/quantestpy/converter.py
@@ -0,0 +1,40 @@
+from quantestpy import TestCircuit
+from qiskit import QuantumCircuit, assemble
+
+
+def _cvt_qiskit_to_test_circuit(
+        qiskit_circuit: QuantumCircuit) -> TestCircuit:
+
+    qobj = assemble(qiskit_circuit)
+    qobj_dict = qobj.to_dict()
+    experiments = qobj_dict["experiments"][0]  # [0] changes list into dict.
+    gates = experiments["instructions"]
+    num_qubits = experiments["config"]["n_qubits"]
+    circuit = TestCircuit(num_qubits)
+
+    # When num_qubits > 2, we must change the below for statement.
+    for gate in gates:
+        # parameter is necessary after implementing parameter in test_circuit
+        # if "params" in gate:
+        #    parameter = gate["params"]
+        # else:
+        #    parameter = []
+
+        if gate["name"] in ["cx", "cnot"]:
+            control_value = [1]
+        else:
+            control_value = []
+
+        gate_test = dict(name=gate["name"],
+                         target_qubit=[gate["qubits"][-1]],
+                         control_qubit=gate["qubits"][:-1],
+                         control_value=control_value)
+        # , parameter=parameter)
+        circuit.add_gate(gate_test)
+
+    return circuit
+
+
+def _cvt_openqasm_to_test_circuit(qasm: str) -> TestCircuit:
+    qiskit_circuit = QuantumCircuit.from_qasm_str(qasm)
+    return _cvt_qiskit_to_test_circuit(qiskit_circuit)
diff --git a/quantestpy/test_circuit.py b/quantestpy/test_circuit.py
index eb233bf..dffeac1 100644
--- a/quantestpy/test_circuit.py
+++ b/quantestpy/test_circuit.py
@@ -282,11 +282,6 @@ def _get_whole_gates(self,) -> np.ndarray:
         return whole_gates
 
 
-def cvt_openqasm_to_test_circuit(qasm: str) -> TestCircuit:
-    """Needs implemantation"""
-    return "Not implemented yet..."
-
-
 if __name__ == "__main__":
     """Example showing how to use TestCircuit class."""
 
diff --git a/test/test_converter.py b/test/test_converter.py
new file mode 100644
index 0000000..5450baf
--- /dev/null
+++ b/test/test_converter.py
@@ -0,0 +1,51 @@
+import unittest
+from qiskit import QuantumCircuit
+
+from quantestpy import TestCircuit
+from quantestpy.converter import _cvt_qiskit_to_test_circuit
+from quantestpy.converter import _cvt_openqasm_to_test_circuit
+
+
+class TestConverter(unittest.TestCase):
+    """
+    How to execute this test:
+    $ pwd
+    {Your directory where you git-cloned quantestpy}/quantestpy
+    $ python -m unittest test.test_converter
+    ...
+    ----------------------------------------------------------------------
+    Ran 2 tests in 0.035s
+
+    OK
+    """
+
+    def test__cvt_qiskit_to_test_circuit(self,):
+        qc = QuantumCircuit(2, 2)
+        qc.h(0)
+        qc.cx(0, 1)
+        actual_circuit = _cvt_qiskit_to_test_circuit(qc)
+
+        expected_circuit = TestCircuit(2)
+        expected_circuit.add_gate(
+            {"name": "h", "target_qubit": [0], "control_qubit": [],
+             "control_value": []})
+        expected_circuit.add_gate({"name": "cx", "target_qubit": [1],
+                                   "control_qubit": [0], "control_value": [1]})
+
+        self.assertEqual(vars(actual_circuit), vars(expected_circuit))
+
+    def test__cvt_openqasm_to_test_circuit(self,):
+        qc = QuantumCircuit(2, 2)
+        qc.h(0)
+        qc.cx(0, 1)
+        qasm = qc.qasm()
+        actual_circuit = _cvt_openqasm_to_test_circuit(qasm)
+
+        expected_circuit = TestCircuit(2)
+        expected_circuit.add_gate(
+            {"name": "h", "target_qubit": [0], "control_qubit": [],
+             "control_value": []})
+        expected_circuit.add_gate({"name": "cx", "target_qubit": [1],
+                                   "control_qubit": [0], "control_value": [1]})
+
+        self.assertEqual(vars(actual_circuit), vars(expected_circuit))