Skip to content

Commit ee10b4d

Browse files
committed
pass tests and parse results as quantumresult
1 parent 734724b commit ee10b4d

File tree

3 files changed

+71
-16
lines changed

3 files changed

+71
-16
lines changed

src/qutip_qip/ionq/converter.py

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from qutip.qip.circuit import QubitCircuit, Gate
1+
from qutip import Qobj
2+
from qutip_qip.circuit import QubitCircuit, CircuitResult
3+
import numpy as np
24

35

46
def convert_qutip_circuit(qc: QubitCircuit) -> dict:
@@ -17,7 +19,11 @@ def convert_qutip_circuit(qc: QubitCircuit) -> dict:
1719
"""
1820
ionq_circuit = []
1921
for gate in qc.gates:
20-
if isinstance(gate, Gate):
22+
if (
23+
hasattr(gate, "name")
24+
and hasattr(gate, "targets")
25+
and hasattr(gate, "controls")
26+
):
2127
ionq_circuit.append(
2228
{
2329
"gate": gate.name,
@@ -28,6 +34,46 @@ def convert_qutip_circuit(qc: QubitCircuit) -> dict:
2834
return ionq_circuit
2935

3036

37+
def convert_ionq_response_to_circuitresult(
38+
ionq_response: dict,
39+
) -> CircuitResult:
40+
"""
41+
Convert an IonQ response to a CircuitResult.
42+
43+
Parameters
44+
----------
45+
ionq_response: dict
46+
The IonQ response.
47+
48+
Returns
49+
-------
50+
CircuitResult
51+
The CircuitResult.
52+
"""
53+
states = list(ionq_response.keys())
54+
# probabilities = list(ionq_response.values())
55+
56+
max_state = max(int(state) for state in states)
57+
num_qubits = int(np.ceil(np.log2(max_state + 1))) if max_state > 0 else 1
58+
59+
final_states = []
60+
final_probabilities = []
61+
62+
for state in states:
63+
binary_state = format(int(state), "0{}b".format(num_qubits))
64+
state_vector = np.zeros((2**num_qubits,), dtype=complex)
65+
index = int(binary_state, 2)
66+
state_vector[index] = 1.0
67+
68+
qobj_state = Qobj(
69+
state_vector, dims=[[2] * num_qubits, [1] * num_qubits]
70+
)
71+
final_states.append(qobj_state)
72+
final_probabilities.append(ionq_response[state])
73+
74+
return CircuitResult(final_states, final_probabilities)
75+
76+
3177
def create_job_body(
3278
circuit: dict,
3379
shots: int,

src/qutip_qip/ionq/job.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Class for a running job."""
22

3-
from .converter import create_job_body
3+
from .converter import create_job_body, convert_ionq_response_to_circuitresult
4+
from qutip_qip.circuit import CircuitResult
45
import requests
56
import time
67

@@ -65,7 +66,7 @@ def get_status(self) -> dict:
6566
self.status = response.json()
6667
return self.status
6768

68-
def get_results(self, polling_rate: int = 1) -> dict:
69+
def get_results(self, polling_rate: int = 1) -> CircuitResult:
6970
"""
7071
Get the results of the job.
7172
@@ -85,7 +86,4 @@ def get_results(self, polling_rate: int = 1) -> dict:
8586
headers=self.headers,
8687
)
8788
response.raise_for_status()
88-
self.results = {
89-
k: int(round(v * self.shots)) for k, v in response.json().items()
90-
}
91-
return self.results
89+
return convert_ionq_response_to_circuitresult(response.json())

tests/test_ionq.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22
from unittest.mock import patch, MagicMock
3-
from qutip.qip.circuit import QubitCircuit, Gate
4-
from qutip.ionq import (
3+
from qutip_qip.circuit import QubitCircuit, Gate
4+
from qutip_qip.ionq import (
55
Provider,
66
IonQSimulator,
77
IonQQPU,
@@ -14,24 +14,28 @@ class TestConverter(unittest.TestCase):
1414
def test_convert_qutip_circuit(self):
1515
# Create a simple QubitCircuit with one gate for testing
1616
qc = QubitCircuit(N=1)
17-
qc.add_gate("X", targets=[0])
17+
qc.add_gate("H", targets=[0])
18+
qc.add_gate("CNOT", targets=[0], controls=[1])
1819
# Convert the qutip_qip circuit to IonQ format
1920
ionq_circuit = convert_qutip_circuit(qc)
20-
expected_output = [{"gate": "X", "targets": [0], "controls": []}]
21+
expected_output = [
22+
{"gate": "H", "targets": [0], "controls": []},
23+
{"gate": "CNOT", "targets": [0], "controls": [1]},
24+
]
2125
self.assertEqual(ionq_circuit, expected_output)
2226

2327

2428
class TestIonQBackend(unittest.TestCase):
2529
def setUp(self):
2630
self.provider = Provider(token="dummy_token")
2731

28-
@patch("qutip.ionq.Provider")
32+
@patch("qutip_qip.ionq.Provider")
2933
def test_simulator_initialization(self, mock_provider):
3034
simulator = IonQSimulator(provider=mock_provider)
3135
self.assertEqual(simulator.provider, mock_provider)
3236
self.assertEqual(simulator.gateset, "qis")
3337

34-
@patch("qutip.ionq.Provider")
38+
@patch("qutip_qip.ionq.Provider")
3539
def test_qpu_initialization(self, mock_provider):
3640
qpu = IonQQPU(provider=mock_provider, qpu="harmony")
3741
self.assertEqual(qpu.provider, mock_provider)
@@ -55,8 +59,15 @@ def test_submit(self, mock_post):
5559

5660
@patch("requests.get")
5761
def test_get_results(self, mock_get):
58-
mock_get.return_value.json.return_value = {"0": 0.5, "1": 0.5}
59-
mock_get.return_value.status_code = 200
62+
# Simulate the status check response and the final result response
63+
mock_get.side_effect = [
64+
MagicMock(
65+
json=lambda: {"status": "completed"}
66+
), # Simulated status check response
67+
MagicMock(
68+
json=lambda: {"0": 0.5, "1": 0.5}
69+
), # Simulated final results response
70+
]
6071
job = Job(
6172
circuit={},
6273
shots=1024,

0 commit comments

Comments
 (0)