quapp-common 0.0.12.dev9__tar.gz → 0.0.12.dev11__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {quapp_common-0.0.12.dev9/quapp_common.egg-info → quapp_common-0.0.12.dev11}/PKG-INFO +20 -1
  2. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/README.md +19 -0
  3. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/pyproject.toml +1 -1
  4. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/bridge.py +25 -11
  5. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/circuit_adapter.py +24 -6
  6. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11/quapp_common.egg-info}/PKG-INFO +20 -1
  7. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/LICENSE +0 -0
  8. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/__init__.py +0 -0
  9. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/async_tasks/__init__.py +0 -0
  10. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/async_tasks/async_invocation_task.py +0 -0
  11. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/async_tasks/async_task.py +0 -0
  12. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/async_tasks/export_circuit_task.py +0 -0
  13. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/async_tasks/post_processing_task.py +0 -0
  14. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/__init__.py +0 -0
  15. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/backend/__init__.py +0 -0
  16. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/backend/invocation.py +0 -0
  17. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/backend/job_fetcher.py +0 -0
  18. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/backend/job_fetching.py +0 -0
  19. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/backend/job_manager.py +0 -0
  20. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/callback/__init__.py +0 -0
  21. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/callback/update_job_metadata.py +0 -0
  22. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/device/__init__.py +0 -0
  23. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/device/device_selection.py +0 -0
  24. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/dispatcher.py +0 -0
  25. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/component/result_serializer.py +0 -0
  26. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/config/__init__.py +0 -0
  27. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/config/logging_config.py +0 -0
  28. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/config/thread_config.py +0 -0
  29. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/__init__.py +0 -0
  30. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/async_task/__init__.py +0 -0
  31. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/async_task/circuit_export/__init__.py +0 -0
  32. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/async_task/circuit_export/backend_holder.py +0 -0
  33. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/async_task/circuit_export/circuit_holder.py +0 -0
  34. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/backend/__init__.py +0 -0
  35. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/backend/backend_information.py +0 -0
  36. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/callback/__init__.py +0 -0
  37. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/callback/callback_url.py +0 -0
  38. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/device/__init__.py +0 -0
  39. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/device/circuit_running_option.py +0 -0
  40. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/promise/__init__.py +0 -0
  41. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/promise/post_processing_promise.py +0 -0
  42. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/promise/promise.py +0 -0
  43. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/request/__init__.py +0 -0
  44. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/request/invocation_request.py +0 -0
  45. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/request/job_fetching_request.py +0 -0
  46. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/request/request.py +0 -0
  47. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/response/__init__.py +0 -0
  48. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/response/authentication.py +0 -0
  49. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/response/custom_header.py +0 -0
  50. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/data/response/job_response.py +0 -0
  51. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/__init__.py +0 -0
  52. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/base_enum.py +0 -0
  53. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/http_header.py +0 -0
  54. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/invocation_step.py +0 -0
  55. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/language.py +0 -0
  56. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/media_type.py +0 -0
  57. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/processing_unit.py +0 -0
  58. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/provider_tag.py +0 -0
  59. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/sdk.py +0 -0
  60. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/status/__init__.py +0 -0
  61. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/status/job_status.py +0 -0
  62. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/status/status_code.py +0 -0
  63. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/enum/token_type.py +0 -0
  64. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/factory/__init__.py +0 -0
  65. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/factory/device_factory.py +0 -0
  66. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/factory/handler_factory.py +0 -0
  67. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/factory/provider_factory.py +0 -0
  68. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/handler/__init__.py +0 -0
  69. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/handler/handler.py +0 -0
  70. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/model/__init__.py +0 -0
  71. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/model/device/__init__.py +0 -0
  72. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/model/device/custom_device.py +0 -0
  73. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/model/device/device.py +0 -0
  74. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/model/invocation.py +0 -0
  75. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/model/provider/__init__.py +0 -0
  76. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/model/provider/provider.py +0 -0
  77. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/util/__init__.py +0 -0
  78. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/util/file_utils.py +0 -0
  79. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/util/http_utils.py +0 -0
  80. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/util/json_parser_utils.py +0 -0
  81. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common/util/response_utils.py +0 -0
  82. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common.egg-info/SOURCES.txt +0 -0
  83. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common.egg-info/dependency_links.txt +0 -0
  84. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common.egg-info/requires.txt +0 -0
  85. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/quapp_common.egg-info/top_level.txt +0 -0
  86. {quapp_common-0.0.12.dev9 → quapp_common-0.0.12.dev11}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.12.dev9
3
+ Version: 0.0.12.dev11
4
4
  Summary: Quapp common library supporting Quapp Platform for Quantum Computing
5
5
  Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
6
6
  License: The MIT License (MIT)
@@ -103,6 +103,25 @@ Notes:
103
103
 
104
104
  ## Recently Changes Highlights
105
105
 
106
+ ### v0.0.12.dev11
107
+ - Enhance: `CircuitAdapter` now emits structured debug logs at each routing
108
+ decision — SDK selected, QASM string length, qubit count, per-SDK adapter
109
+ chosen, `tk_to_braket` return type (tuple vs bare Circuit), DenseMatrix
110
+ fallback for unrecognized/parametric gates in `_qiskit_to_qulacs`, and QUBO
111
+ entry counts before and after parsing.
112
+ - Enhance: `SubprocessBridge` now emits debug logs on initialisation
113
+ (`language`, `sdk`), `processing()` (input keys, JS status, adapted circuit
114
+ type), and `post_processing()` (job-result type, serialised keys, JS status,
115
+ result type); subprocess failures are additionally promoted to `logger.error`
116
+ before the `RuntimeError` is raised.
117
+
118
+ ### v0.0.12.dev10
119
+ - Fix: `CircuitAdapter._adapt_openqasm` for `Sdk.BRAKET` now handles the
120
+ breaking API change in `pytket-braket >= 0.35`, where `tk_to_braket` returns
121
+ a `(Circuit, n_shots)` tuple instead of a bare `Circuit` — the method unpacks
122
+ the first element when a tuple is returned and passes through the value
123
+ unchanged for older versions.
124
+
106
125
  ### v0.0.12.dev9
107
126
  - Fix: `QulacsInvocation._get_qubit_amount` now handles OpenQASM string input —
108
127
  when a JS job submits an OpenQASM 2.0 string circuit, the method parses the
@@ -64,6 +64,25 @@ Notes:
64
64
 
65
65
  ## Recently Changes Highlights
66
66
 
67
+ ### v0.0.12.dev11
68
+ - Enhance: `CircuitAdapter` now emits structured debug logs at each routing
69
+ decision — SDK selected, QASM string length, qubit count, per-SDK adapter
70
+ chosen, `tk_to_braket` return type (tuple vs bare Circuit), DenseMatrix
71
+ fallback for unrecognized/parametric gates in `_qiskit_to_qulacs`, and QUBO
72
+ entry counts before and after parsing.
73
+ - Enhance: `SubprocessBridge` now emits debug logs on initialisation
74
+ (`language`, `sdk`), `processing()` (input keys, JS status, adapted circuit
75
+ type), and `post_processing()` (job-result type, serialised keys, JS status,
76
+ result type); subprocess failures are additionally promoted to `logger.error`
77
+ before the `RuntimeError` is raised.
78
+
79
+ ### v0.0.12.dev10
80
+ - Fix: `CircuitAdapter._adapt_openqasm` for `Sdk.BRAKET` now handles the
81
+ breaking API change in `pytket-braket >= 0.35`, where `tk_to_braket` returns
82
+ a `(Circuit, n_shots)` tuple instead of a bare `Circuit` — the method unpacks
83
+ the first element when a tuple is returned and passes through the value
84
+ unchanged for older versions.
85
+
67
86
  ### v0.0.12.dev9
68
87
  - Fix: `QulacsInvocation._get_qubit_amount` now handles OpenQASM string input —
69
88
  when a JS job submits an OpenQASM 2.0 string circuit, the method parses the
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "quapp-common"
7
- version = "0.0.12.dev9"
7
+ version = "0.0.12.dev11"
8
8
  description = "Quapp common library supporting Quapp Platform for Quantum Computing"
9
9
  readme = "README.md"
10
10
  authors = [{ name = "CITYNOW Co. Ltd. ", email = "corp@citynow.vn" }]
@@ -30,6 +30,7 @@ class SubprocessBridge:
30
30
  def __init__(self, language: Language, sdk: Sdk):
31
31
  self.language = language
32
32
  self.sdk = sdk
33
+ logger.debug(f"SubprocessBridge initialized | language={language.value} | sdk={sdk}")
33
34
 
34
35
  def processing(self, invocation_input: dict):
35
36
  """Call JS handler's processing() and convert a result to a native circuit.
@@ -43,24 +44,31 @@ class SubprocessBridge:
43
44
  Raises:
44
45
  RuntimeError: If the JS subprocess returns an error status.
45
46
  """
46
- logger.info(
47
- f"SubprocessBridge.processing: dispatching to {self.language.value}")
47
+ logger.info(f"SubprocessBridge.processing: dispatching to {self.language.value} | sdk={self.sdk}")
48
+ logger.debug(f"SubprocessBridge.processing: input_keys={list(invocation_input.keys())}")
48
49
 
49
50
  result = SubprocessDispatcher.dispatch(self.language, {
50
51
  "action": "processing",
51
52
  "input" : invocation_input
52
53
  })
53
54
 
54
- if result.get("status") == "error":
55
+ status = result.get("status")
56
+ logger.debug(f"SubprocessBridge.processing: JS status={status}")
57
+
58
+ if status == "error":
59
+ logger.error(f"SubprocessBridge.processing: JS error={result.get('error')}")
55
60
  raise RuntimeError(f"JS processing failed: {result.get('error')}")
56
61
 
57
62
  payload = result.get("result")
58
63
  if payload is None:
59
64
  raise RuntimeError("JS processing returned no 'result' field")
60
- logger.debug(
61
- f"SubprocessBridge.processing: JS returned format={payload.get('format')}")
62
65
 
63
- return CircuitAdapter.adapt(self.sdk, payload)
66
+ fmt = payload.get("format")
67
+ logger.debug(f"SubprocessBridge.processing: JS returned format={fmt}; adapting for sdk={self.sdk}")
68
+
69
+ circuit = CircuitAdapter.adapt(self.sdk, payload)
70
+ logger.info(f"SubprocessBridge.processing: circuit adapted successfully | type={type(circuit).__name__}")
71
+ return circuit
64
72
 
65
73
  def post_processing(self, job_result):
66
74
  """Serialize a job result, send to JS handler's postProcessing(), return a result.
@@ -74,21 +82,27 @@ class SubprocessBridge:
74
82
  Raises:
75
83
  RuntimeError: If the JS subprocess returns an error status.
76
84
  """
77
- logger.info(
78
- f"SubprocessBridge.post_processing: dispatching to {self.language.value}")
85
+ logger.info(f"SubprocessBridge.post_processing: dispatching to {self.language.value}")
86
+ logger.debug(f"SubprocessBridge.post_processing: job_result type={type(job_result).__name__}")
79
87
 
80
88
  serialized = ResultSerializer.serialize(job_result)
89
+ logger.debug(f"SubprocessBridge.post_processing: serialized result keys={list(serialized.keys()) if isinstance(serialized, dict) else type(serialized).__name__}")
81
90
 
82
91
  result = SubprocessDispatcher.dispatch(self.language, {
83
92
  "action" : "post_processing",
84
93
  "job_result": serialized
85
94
  })
86
95
 
87
- if result.get("status") == "error":
88
- raise RuntimeError(
89
- f"JS post_processing failed: {result.get('error')}")
96
+ status = result.get("status")
97
+ logger.debug(f"SubprocessBridge.post_processing: JS status={status}")
98
+
99
+ if status == "error":
100
+ logger.error(f"SubprocessBridge.post_processing: JS error={result.get('error')}")
101
+ raise RuntimeError(f"JS post_processing failed: {result.get('error')}")
90
102
 
91
103
  payload = result.get("result")
92
104
  if payload is None:
93
105
  raise RuntimeError("JS post_processing returned no 'result' field")
106
+
107
+ logger.info(f"SubprocessBridge.post_processing: completed successfully | result type={type(payload).__name__}")
94
108
  return payload
@@ -24,6 +24,7 @@ class CircuitAdapter:
24
24
  def adapt(sdk: Sdk, result: dict):
25
25
  """Route to the appropriate adapter based on the 'format' field."""
26
26
  fmt = result.get("format")
27
+ logger.debug(f"adapt() called | sdk={sdk} | format={fmt}")
27
28
  if fmt == "openqasm":
28
29
  circuit = result.get("circuit")
29
30
  if circuit is None:
@@ -35,25 +36,33 @@ class CircuitAdapter:
35
36
  raise ValueError("Missing 'qubo' field in qubo response")
36
37
  return CircuitAdapter._adapt_qubo(sdk, qubo)
37
38
  elif fmt == "json":
39
+ logger.debug("Returning raw JSON data pass-through")
38
40
  return result.get("data")
39
41
  raise ValueError(f"Unsupported circuit interchange format: {fmt}")
40
42
 
41
43
  @staticmethod
42
44
  def _adapt_openqasm(sdk, qasm_str):
43
45
  """Convert an OpenQASM 2.0 string to a native SDK circuit object."""
44
- logger.debug(f"Adapting OpenQASM circuit for SDK: {sdk}")
46
+ logger.debug(f"Adapting OpenQASM circuit for SDK: {sdk} | qasm_length={len(qasm_str)}")
45
47
 
46
48
  if sdk == Sdk.QISKIT:
49
+ logger.debug("Converting OpenQASM via Qiskit QuantumCircuit.from_qasm_str")
47
50
  from qiskit import QuantumCircuit
48
51
  return QuantumCircuit.from_qasm_str(qasm_str)
49
52
 
50
53
  elif sdk == Sdk.BRAKET:
54
+ logger.debug("Converting OpenQASM via pytket -> tk_to_braket")
51
55
  import importlib
52
56
  from pytket.qasm import circuit_from_qasm_str
53
57
  tk_to_braket = importlib.import_module("pytket.extensions.braket").tk_to_braket
54
- return tk_to_braket(circuit_from_qasm_str(qasm_str))
58
+ result = tk_to_braket(circuit_from_qasm_str(qasm_str))
59
+ # tk_to_braket returns (Circuit, n_shots) in pytket-braket >= 0.35
60
+ is_tuple = isinstance(result, tuple)
61
+ logger.debug(f"tk_to_braket returned tuple={is_tuple}; unpacking index 0" if is_tuple else "tk_to_braket returned Circuit directly")
62
+ return result[0] if is_tuple else result
55
63
 
56
64
  elif sdk == Sdk.PENNYLANE:
65
+ logger.debug("Converting OpenQASM via PennyLane qml.from_qasm wrapper")
57
66
  import pennylane as qml
58
67
  # PennyLane >=0.37 treats QASM `measure` statements as mid-circuit
59
68
  # measurements returning MeasurementValue, which fails QNode
@@ -72,6 +81,7 @@ class CircuitAdapter:
72
81
  # fresh `qml.probs` over all qubits, so the wires are visible in
73
82
  # both `QuantumTape` capture and full QNode execution.
74
83
  num_wires = CircuitAdapter._count_qasm_qubits(qasm_str)
84
+ logger.debug(f"PennyLane: detected {num_wires} qubits; wrapping with qml.probs over all wires")
75
85
  base_fn = qml.from_qasm(qasm_str, measurements=[])
76
86
 
77
87
  def _circuit():
@@ -83,28 +93,32 @@ class CircuitAdapter:
83
93
  return _circuit
84
94
 
85
95
  elif sdk == Sdk.PYQUIL:
96
+ logger.debug("Converting OpenQASM via pytket -> tk_to_pyquil")
86
97
  import importlib
87
98
  from pytket.qasm import circuit_from_qasm_str
88
99
  tk_to_pyquil = importlib.import_module("pytket.extensions.pyquil").tk_to_pyquil
89
100
  return tk_to_pyquil(circuit_from_qasm_str(qasm_str))
90
101
 
91
102
  elif sdk == Sdk.QIBO:
103
+ logger.debug("Converting OpenQASM via Qibo Circuit.from_qasm")
92
104
  from qibo.models import Circuit
93
105
  return Circuit.from_qasm(qasm_str)
94
106
 
95
107
  elif sdk == Sdk.QULACS:
108
+ logger.debug("Converting OpenQASM for Qulacs via Qiskit bridge")
96
109
  # Try the Qiskit bridge first; fall back to raw pass-through if
97
110
  # qiskit is not installed or the conversion fails.
98
111
  try:
99
112
  from qiskit import QuantumCircuit as QiskitCircuit
100
- return CircuitAdapter._qiskit_to_qulacs(
101
- QiskitCircuit.from_qasm_str(qasm_str)
102
- )
113
+ qiskit_circ = QiskitCircuit.from_qasm_str(qasm_str)
114
+ logger.debug(f"Qiskit parsed circuit: num_qubits={qiskit_circ.num_qubits} num_gates={len(qiskit_circ.data)}")
115
+ return CircuitAdapter._qiskit_to_qulacs(qiskit_circ)
103
116
  except Exception as e:
104
117
  logger.warning(f"Qiskit bridge failed for Qulacs ({e}); falling back to raw OpenQASM pass-through")
105
118
  return qasm_str
106
119
 
107
120
  elif sdk == Sdk.CUDA_QUANTUM:
121
+ logger.debug("CUDA-Q: passing OpenQASM string through directly")
108
122
  # CUDA-Q accepts OpenQASM directly via kernel builder
109
123
  return qasm_str
110
124
 
@@ -123,7 +137,7 @@ class CircuitAdapter:
123
137
  JS returns keys like "x0,x1" as strings. We parse them into tuple keys
124
138
  for dimod's from_qubo() method.
125
139
  """
126
- logger.debug(f"Adapting QUBO for SDK: {sdk}")
140
+ logger.debug(f"Adapting QUBO for SDK: {sdk} | num_entries={len(qubo_raw)}")
127
141
 
128
142
  qubo_dict = {}
129
143
  for key, val in qubo_raw.items():
@@ -133,6 +147,7 @@ class CircuitAdapter:
133
147
  else:
134
148
  qubo_dict[(key, key)] = val
135
149
 
150
+ logger.debug(f"QUBO parsed: {len(qubo_dict)} entries -> BinaryQuadraticModel")
136
151
  from dimod import BinaryQuadraticModel
137
152
  return BinaryQuadraticModel.from_qubo(qubo_dict)
138
153
 
@@ -148,6 +163,7 @@ class CircuitAdapter:
148
163
  from qulacs.gate import DenseMatrix
149
164
 
150
165
  n = qiskit_circ.num_qubits
166
+ logger.debug(f"_qiskit_to_qulacs: num_qubits={n} num_instructions={len(qiskit_circ.data)}")
151
167
  qulacs_circ = QulacsCirucit(n)
152
168
  qubit_map = {bit: idx for idx, bit in enumerate(qiskit_circ.qubits)}
153
169
 
@@ -181,6 +197,8 @@ class CircuitAdapter:
181
197
  # as a DenseMatrix. Single-qubit gates have no ordering
182
198
  # ambiguity; multi-qubit gates are passed with qulacs'
183
199
  # index order matching Qiskit's instruction qubit order.
200
+ logger.debug(f"Gate '{name}' not in named map; converting via DenseMatrix on qubits={qubits}")
184
201
  qulacs_circ.add_gate(DenseMatrix(qubits, gate.to_matrix()))
185
202
 
203
+ logger.debug(f"_qiskit_to_qulacs: conversion complete")
186
204
  return qulacs_circ
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: quapp-common
3
- Version: 0.0.12.dev9
3
+ Version: 0.0.12.dev11
4
4
  Summary: Quapp common library supporting Quapp Platform for Quantum Computing
5
5
  Author-email: "CITYNOW Co. Ltd. " <corp@citynow.vn>
6
6
  License: The MIT License (MIT)
@@ -103,6 +103,25 @@ Notes:
103
103
 
104
104
  ## Recently Changes Highlights
105
105
 
106
+ ### v0.0.12.dev11
107
+ - Enhance: `CircuitAdapter` now emits structured debug logs at each routing
108
+ decision — SDK selected, QASM string length, qubit count, per-SDK adapter
109
+ chosen, `tk_to_braket` return type (tuple vs bare Circuit), DenseMatrix
110
+ fallback for unrecognized/parametric gates in `_qiskit_to_qulacs`, and QUBO
111
+ entry counts before and after parsing.
112
+ - Enhance: `SubprocessBridge` now emits debug logs on initialisation
113
+ (`language`, `sdk`), `processing()` (input keys, JS status, adapted circuit
114
+ type), and `post_processing()` (job-result type, serialised keys, JS status,
115
+ result type); subprocess failures are additionally promoted to `logger.error`
116
+ before the `RuntimeError` is raised.
117
+
118
+ ### v0.0.12.dev10
119
+ - Fix: `CircuitAdapter._adapt_openqasm` for `Sdk.BRAKET` now handles the
120
+ breaking API change in `pytket-braket >= 0.35`, where `tk_to_braket` returns
121
+ a `(Circuit, n_shots)` tuple instead of a bare `Circuit` — the method unpacks
122
+ the first element when a tuple is returned and passes through the value
123
+ unchanged for older versions.
124
+
106
125
  ### v0.0.12.dev9
107
126
  - Fix: `QulacsInvocation._get_qubit_amount` now handles OpenQASM string input —
108
127
  when a JS job submits an OpenQASM 2.0 string circuit, the method parses the