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

Implementing the method get_result() #94

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 3 additions & 3 deletions qiskit_ibm_transpiler/ai/synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
from multiprocessing import cpu_count
from typing import Dict, List, Union
from typing import List, Union

from qiskit.circuit.exceptions import CircuitError
from qiskit.converters import circuit_to_dag
Expand Down Expand Up @@ -77,7 +77,7 @@ def synth_nodes(self, nodes):
originals.append(orig)
except CircuitError:
logger.warning(
f"Error getting synth input from node. Skipping ai transpilation."
"Error getting synth input from node. Skipping ai transpilation."
)
return [], []

Expand Down Expand Up @@ -109,7 +109,7 @@ def synth_nodes(self, nodes):
return outputs, nodes

def run(self, dag: DAGCircuit):
logger.info(f"Requesting synthesis to the service")
logger.info("Requesting synthesis to the service")

future_list = []

Expand Down
5 changes: 4 additions & 1 deletion qiskit_ibm_transpiler/transpiler_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ def run(
The transpiled circuit(s)

"""
logger.info(f"Requesting transpile to the service")
logger.info("Requesting transpile to the service")
transpile_result = self.transpiler_service.transpile(
circuits=circuits,
backend=self.backend_name,
Expand All @@ -125,3 +125,6 @@ def run(

logger.info("Qiskit IBM Transpiler returned a result")
return transpile_result

def get_result(self, task_id:str, **kwargs):
return self.transpiler_service.get_result(task_id=task_id, **kwargs)
12 changes: 11 additions & 1 deletion qiskit_ibm_transpiler/wrappers/ai_routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
from qiskit_ibm_transpiler.utils import get_circuit_from_qasm, input_to_qasm
from .base import QiskitTranspilerService
from typing import List, Union, Literal
import logging


logger = logging.getLogger(__name__)
# TODO: Reuse this code, it's repeated several times
OptimizationOptions = Literal["n_cnots", "n_gates", "cnot_layers", "layers", "noise"]

Expand Down Expand Up @@ -62,3 +63,12 @@ def routing(
routing_resp["layout"]["initial"],
routing_resp["layout"]["final"],
)

def get_result(
self, task_id: str
) -> Union[QuantumCircuit, List[QuantumCircuit], str, List[str]]:
routing_resp = self.get_task_result(endpoint="routing", task_id=task_id)

routed_circuit = get_circuit_from_qasm(routing_resp["qasm"])

return routed_circuit
53 changes: 48 additions & 5 deletions qiskit_ibm_transpiler/wrappers/ai_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@

from .base import QiskitTranspilerService

logging.basicConfig()
logging.getLogger(__name__).setLevel(logging.INFO)
logger = logging.getLogger(__name__)


class AICliffordAPI(QiskitTranspilerService):
Expand Down Expand Up @@ -61,7 +60,7 @@ def transpile(
)
else:
raise (
f"ERROR. Either a 'coupling_map' or a 'backend_name' must be provided."
"ERROR. Either a 'coupling_map' or a 'backend_name' must be provided."
)

results = []
Expand All @@ -72,6 +71,20 @@ def transpile(
results.append(None)
return results

def get_result(
self, task_id: str
):
transpile_resp = self.get_task_result(endpoint="transpile", task_id=task_id)
results = []

for res in transpile_resp:
try:
results.append(QuantumCircuit.from_qasm_str(res["qasm"]))
except Exception as ex:
logger.error("Error transforming the result to a QuantumCircuit object")
raise

return results

class AILinearFunctionAPI(QiskitTranspilerService):
"""A helper class that covers some basic funcionality from the Linear Function AI Synthesis API"""
Expand Down Expand Up @@ -111,7 +124,7 @@ def transpile(
)
else:
raise (
f"ERROR. Either a 'coupling_map' or a 'backend_name' must be provided."
"ERROR. Either a 'coupling_map' or a 'backend_name' must be provided."
)

results = []
Expand All @@ -122,6 +135,21 @@ def transpile(
results.append(None)
return results

def get_result(
self, task_id: str
):
transpile_resp = self.get_task_result(endpoint="transpile", task_id=task_id)
results = []

for res in transpile_resp:
try:
results.append(QuantumCircuit.from_qasm_str(res["qasm"]))
except Exception as ex:
logger.error("Error transforming the result to a QuantumCircuit object")
raise

return results


class AIPermutationAPI(QiskitTranspilerService):
"""A helper class that covers some basic funcionality from the Permutation AI Synthesis API"""
Expand Down Expand Up @@ -158,7 +186,7 @@ def transpile(
)
else:
raise (
f"ERROR. Either a 'coupling_map' or a 'backend_name' must be provided."
"ERROR. Either a 'coupling_map' or a 'backend_name' must be provided."
)

results = []
Expand All @@ -168,3 +196,18 @@ def transpile(
else:
results.append(None)
return results

def get_result(
self, task_id: str
):
transpile_resp = self.get_task_result(endpoint="transpile", task_id=task_id)
results = []

for res in transpile_resp:
try:
results.append(QuantumCircuit.from_qasm_str(res["qasm"]))
except Exception as ex:
logger.error("Error transforming the result to a QuantumCircuit object")
raise

return results
39 changes: 25 additions & 14 deletions qiskit_ibm_transpiler/wrappers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import json
import logging
import os
from http import HTTPStatus
from pathlib import Path
from typing import Dict
from urllib.parse import urljoin
Expand Down Expand Up @@ -103,6 +102,29 @@ def get_supported_backends(self):

return resp

def get_task_result(
self,
endpoint: str,
task_id: str,
):
result = BackendTaskError(
status="PENDING",
msg=(
f"The background task {task_id} timed out. Try to update the client's timeout config, "
"review your task or use the get_result() method to get the result manually"
),
)

resp = self.request_status(endpoint=endpoint, task_id=task_id)
if resp.get("state") == "SUCCESS":
result = resp.get("result")
elif resp.get("state") == "FAILURE":
logger.error("The request FAILED")
result = BackendTaskError(
status="FAILURE", msg=f"The background task {task_id} FAILED"
)
return result

def request_status(self, endpoint, task_id):
def _giveup(e):
# Only retry 520 errors
Expand Down Expand Up @@ -158,20 +180,9 @@ def _request_and_wait(self, endpoint: str, body: Dict, params: Dict):
resp = resp.json()
task_id = resp.get("task_id")

result = BackendTaskError(
status="PENDING",
msg=f"The background task {task_id} timed out. Try to update the client's timeout config or review your task",
)

resp = self.request_status(endpoint, task_id)
if resp.get("state") == "SUCCESS":
result = resp.get("result")
elif resp.get("state") == "FAILURE":
logger.error("The request FAILED")
result = BackendTaskError(
status="FAILURE", msg=f"The background task {task_id} FAILED"
)
logger.info(f"Task {task_id} submitted")

result = self.get_task_result(endpoint=endpoint, task_id=task_id)
if isinstance(result, BackendTaskError):
# TODO: Shall we show this "The background task 99cf52d2-3942-4ae5-b2a7-d672af7f1216 FAILED" to the user?
logger.error(f"Failed to get a result for {endpoint}: {result.msg}")
Expand Down
21 changes: 19 additions & 2 deletions qiskit_ibm_transpiler/wrappers/transpile.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
import logging
from typing import Dict, List, Union, Literal

import numpy as np
from qiskit import QuantumCircuit, QuantumRegister
from qiskit.circuit import QuantumCircuit, QuantumRegister, Qubit
from qiskit.transpiler import TranspileLayout
from qiskit.transpiler.layout import Layout
Expand Down Expand Up @@ -98,6 +96,25 @@ def transpile(
else transpiled_circuits[0]
)

def get_result(
self, task_id: str
):
transpile_resp = self.get_task_result(endpoint="transpile", task_id=task_id)
transpiled_circuits = []

for res in transpile_resp:
try:
transpiled_circuits.append(get_circuit_from_qasm(res["qasm"]))
except Exception as ex:
logger.error("Error transforming the result to a QuantumCircuit object")
raise

return (
transpiled_circuits
if len(transpiled_circuits) > 1
else transpiled_circuits[0]
)


def _get_circuit_from_result(transpile_resp, orig_circuit):
transpiled_circuit = get_circuit_from_qasm(transpile_resp["qasm"])
Expand Down
Loading