Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a4f4b34
feat: to_other_language Braket without QASM
JulienCalistoTD Aug 6, 2025
50d8018
feat: add pre_transpile attribute and update grouping methods for Exp…
JulienCalistoTD Aug 7, 2025
0850065
feat: update observable pre_transpile attribute
JulienCalistoTD Aug 7, 2025
29587e0
Merge branch 'fix-pauli-obs' into feat-to-other-language-AWS
JulienCalistoTD Aug 14, 2025
de2e44e
chore: Files formated
github-actions[bot] Aug 14, 2025
2564cd0
refactor: update Braket observable not handling paulistring
JulienCalistoTD Aug 14, 2025
46a5b3b
Merge branch 'feat-to-other-language-AWS' of https://github.com/Colib…
JulienCalistoTD Aug 14, 2025
00d7a6b
Merge branch 'dev' into feat-to-other-language-AWS
JulienCalistoTD Oct 2, 2025
e3092f8
chore: Files formated
github-actions[bot] Oct 2, 2025
7f16626
feat: run with DirectReservation logic
MoHermes Oct 27, 2025
cf97799
Update mpqp/core/instruction/gates/custom_gate.py
Henri-ColibrITD Oct 31, 2025
99182ab
Update mpqp/core/instruction/measurement/expectation_value.py
Henri-ColibrITD Oct 31, 2025
89ba320
Apply suggestion from @Henri-ColibrITD
Henri-ColibrITD Oct 31, 2025
8333dfa
refactor: replace pauli_string_from_str with PauliString.from_str in …
JulienCalistoTD Nov 4, 2025
ac548b0
Merge branch 'feat-to-other-language-AWS' of https://github.com/Colib…
JulienCalistoTD Nov 4, 2025
91250d2
Merge branch 'dev' into feat-to-other-language-AWS
JulienCalistoTD Nov 4, 2025
ee3382c
feat: add _sympy_to_braket_param function for parameter conversion
JulienCalistoTD Nov 4, 2025
d539467
chore: Files formated
github-actions[bot] Nov 4, 2025
4fbbf54
refactor: improve exception handling and clean up unused code in circ…
JulienCalistoTD Nov 4, 2025
0f04b8d
Merge branch 'feat-to-other-language-AWS' of https://github.com/Colib…
JulienCalistoTD Nov 4, 2025
d08a496
refactor: enhance error messages and clean up unused imports in vario…
JulienCalistoTD Nov 4, 2025
75da432
chore: Files formated
github-actions[bot] Nov 4, 2025
b3056c6
refactor: remove unused import of contextlib in test_basis.py
JulienCalistoTD Nov 4, 2025
c67082f
Merge branch 'feat-to-other-language-AWS' of https://github.com/Colib…
JulienCalistoTD Nov 4, 2025
00f753f
refactor: improve formatting of list comprehension in ExpectationMeas…
JulienCalistoTD Nov 4, 2025
be33d49
chore: Files formated
github-actions[bot] Nov 4, 2025
e1478d0
feat: modify DirectReservation handling logic
MoHermes Nov 18, 2025
bd692ff
Merge branch 'feat-to-other-language-AWS' into feat-braket-direct-res…
MoHermes Nov 25, 2025
e714949
Merge branch 'feat-braket-direct-reservation' into feat-to-other-lang…
JulienCalistoTD Nov 25, 2025
3b1cf62
Merge branch 'feat-to-other-language-AWS' of https://github.com/Colib…
JulienCalistoTD Nov 25, 2025
19cbbb7
refactor: remove conditional_typechecked decorator from AWS Braket fu…
JulienCalistoTD Nov 25, 2025
d3717d7
chore: Files formated
github-actions[bot] Nov 25, 2025
011013c
fix: type errors
MoHermes Nov 25, 2025
2bb3c2f
chore: update direct resrvation using aws braket device
MoHermes Nov 26, 2025
5d8e814
chore: replace resrvation_arn with provider options dict
MoHermes Dec 8, 2025
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
35 changes: 26 additions & 9 deletions mpqp/core/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1383,16 +1383,33 @@ def to_other_language(
"Cannot simulate noisy circuit with CRk gate due to "
"an error on AWS Braket side."
)
from braket.circuits import Circuit as BracketCircuit

qasm3_code = circuit.to_other_language(
Language.QASM3,
skip_pre_measure=skip_pre_measure,
skip_measurements=skip_measurements,
)

from mpqp.qasm.qasm_to_braket import qasm3_to_braket_Circuit

braket_circuit = qasm3_to_braket_Circuit(qasm3_code)
braket_circuit = BracketCircuit()
for instruction in circuit.instructions:
if isinstance(instruction, (Barrier, Breakpoint)):
continue
if isinstance(instruction, Measure):
if not skip_pre_measure:
for pre_measure in instruction.pre_measure:
bracket_pre_measure = pre_measure.to_other_language(
Language.BRAKET
)
braket_circuit.add(bracket_pre_measure, instruction.targets)
if not skip_measurements:
if isinstance(instruction, BasisMeasure):
braket_circuit.measure(instruction.targets)
continue
braket_instr = instruction.to_other_language(Language.BRAKET)
try:
target = instruction.targets
if isinstance(instruction, ControlledGate):
target = instruction.controls + target
braket_circuit.add_instruction(braket_instr, target=target)
except Exception as e:
raise ValueError(
f"{type(braket_instr)}{braket_instr} cannot be added to the braket circuit: {e}"
)

if len(self.noises) == 0:
return braket_circuit
Expand Down
26 changes: 26 additions & 0 deletions mpqp/core/instruction/gates/custom_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,32 @@ def to_other_language(
dummy_circuit.rx(param, 0)
return dummy_circuit.to_gate(label="CustomGate")
return UnitaryGate(self.matrix)
elif language == Language.BRAKET:
from sympy import Expr

gate_symbols = set().union(
*(
elt.free_symbols
for elt in self.matrix.flatten()
if isinstance(elt, Expr)
)
)

if len(gate_symbols) > 0:
if not printing:
raise ValueError(
"Custom gates defined with symbolic variables cannot be "
"exported to Braket for now (only numerical matrices are supported)."
)
return None
else:
from braket.circuits import Instruction as BraketInstruction
from braket.circuits.gates import Unitary as BraketUnitary

return BraketInstruction(
operator=BraketUnitary(self.definition.matrix),
target=list(range(self.nb_qubits)),
)
elif language == Language.QASM2:
from qiskit import QuantumCircuit, qasm2

Expand Down
81 changes: 56 additions & 25 deletions mpqp/core/instruction/gates/native_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
if TYPE_CHECKING:
from sympy import Expr
from qiskit.circuit import Parameter
from braket.circuits import FreeParameter

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -84,6 +85,22 @@ def _qiskit_parameter_adder(
return qiskit_param


def _sympy_to_braket_param(val: Expr | float) -> "float | FreeParameter":
from sympy import Expr
from braket.circuits import FreeParameter

if isinstance(val, Expr):
if val.free_symbols:
return FreeParameter(str(val)) # note: Braket won't parse expressions
else:
try:
return float(val.evalf()) # pyright: ignore[reportArgumentType]
except Exception as e:
raise ValueError(f"Failed to evaluate sympy expression '{val}': {e}")
else:
return float(val)


class NativeGate(Gate, SimpleClassReprABC):
"""The standard on which we rely, OpenQASM, comes with a set of gates
supported by default. More complicated gates can be defined by the user.
Expand Down Expand Up @@ -224,24 +241,25 @@ def to_other_language(
language: Language = Language.QISKIT,
qiskit_parameters: Optional[set["Parameter"]] = None,
):
if qiskit_parameters is None:
qiskit_parameters = set()

try:
theta = float(self.theta)
except:
theta = self.theta
if language == Language.QISKIT:
if qiskit_parameters is None:
qiskit_parameters = set()
return self.qiskit_gate(_qiskit_parameter_adder(theta, qiskit_parameters))
elif language == Language.BRAKET:
from sympy import Expr
from braket.circuits import Instruction

# TODO: handle symbolic parameters for Braket
if isinstance(theta, Expr):
raise NotImplementedError(
"Symbolic expressions are not yet supported for braket "
"export, this feature is coming very soon!"
)
return self.braket_gate(theta)
connection = self.targets
if isinstance(self, ControlledGate):
connection += self.controls
return Instruction(
operator=self.braket_gate(_sympy_to_braket_param(theta)),
target=list(range(len(connection))),
)
elif language == Language.CIRQ:
return self.cirq_gate(theta)
if language == Language.QASM2:
Expand Down Expand Up @@ -346,7 +364,14 @@ def to_other_language(
if language == Language.QISKIT:
return self.qiskit_gate()
elif language == Language.BRAKET:
return self.braket_gate()
from braket.circuits import Instruction

connection = self.targets
if isinstance(self, ControlledGate):
connection += self.controls
return Instruction(
operator=self.braket_gate(), target=list(range(len(connection)))
)
elif language == Language.CIRQ:
return self.cirq_gate
elif language == Language.QASM2:
Expand Down Expand Up @@ -430,7 +455,14 @@ def to_other_language(
return self.qiskit_gate(label=self.label)
return self.qiskit_gate()
elif language == Language.BRAKET:
return self.braket_gate()
from braket.circuits import Instruction

connection = self.targets
if isinstance(self, ControlledGate):
connection += self.controls
return Instruction(
operator=self.braket_gate(), target=list(range(len(connection)))
)
elif language == Language.CIRQ:
return self.cirq_gate
elif language == Language.QASM2:
Expand Down Expand Up @@ -1079,20 +1111,19 @@ def to_other_language(
lam=_qiskit_parameter_adder(self.gamma, qiskit_parameters),
)
elif language == Language.BRAKET:
from sympy import Expr

# TODO handle symbolic parameters
if (
isinstance(self.theta, Expr)
or isinstance(self.phi, Expr)
or isinstance(self.gamma, Expr)
):
raise NotImplementedError(
"Symbolic expressions are not yet supported for braket "
"export, this feature is coming very soon!"
)
from braket.circuits import Instruction

return self.braket_gate(self.theta, self.phi, self.gamma)
connection = self.targets
if isinstance(self, ControlledGate):
connection += self.controls
return Instruction(
operator=self.braket_gate(
_sympy_to_braket_param(self.theta),
_sympy_to_braket_param(self.phi),
_sympy_to_braket_param(self.gamma),
),
target=list(range(len(connection))),
)
elif language == Language.CIRQ:
return self.cirq_gate(self.theta, self.phi, self.gamma)
elif language == Language.QASM2:
Expand Down
33 changes: 31 additions & 2 deletions mpqp/core/instruction/measurement/expectation_value.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ def __init__(
self._is_diagonal = None
self._diag_elements: Optional[npt.NDArray[np.float64]] = None
self.label = label
self.transpile = None
"See parameter description."
self.pre_transpile = None

if isinstance(observable, PauliString):
self.nb_qubits = observable.nb_qubits
Expand Down Expand Up @@ -306,6 +306,10 @@ def to_other_language(

return QLMObservable(self.nb_qubits, matrix=self.matrix)
elif language == Language.BRAKET:
# TODO: Braket does not handle pauli with coef because it uses QASM2
# if self._pauli_string:
# return self.pauli_string.to_other_language(Language.BRAKET)
# else:
from braket.circuits.observables import Hermitian

return Hermitian(
Expand Down Expand Up @@ -380,7 +384,7 @@ def __init__(
targets: Optional[list[int]] = None,
shots: int = 0,
commuting_type: CommutingTypes = CommutingTypes.QUBITWISE,
grouping_method: GroupingMethods = GroupingMethods.GREEDY,
grouping_method: GroupingMethods = GroupingMethods.QISKIT,
label: Optional[str] = None,
optimize_measurement: Optional[bool] = True,
optim_diagonal: Optional[bool] = False,
Expand All @@ -397,6 +401,7 @@ def __init__(
"""See parameter description."""
self.optimize_measurement = optimize_measurement
"""See parameter description."""
self.pre_transpile = None
if isinstance(observable, Observable):
observable = [observable]
else:
Expand All @@ -417,6 +422,7 @@ def __init__(
if obs.label is None:
while f"{default_label}_{label_counter}" in label_defined:
label_counter += 1

# Create a new instance of Observable with the new label
new_obs = Observable.__new__(Observable)
for attr, val in obs.__dict__.items():
Expand Down Expand Up @@ -500,6 +506,29 @@ def get_pauli_grouping(self) -> list[list[PauliStringMonomial]]:
from mpqp.tools.pauli_grouping import pauli_grouping_greedy

return pauli_grouping_greedy(unique_monos, self.commuting_type)
elif self.grouping_method == GroupingMethods.QISKIT:
from qiskit.quantum_info import PauliList

pauli_labels = [mono.short_name for mono in unique_monos]
pauli_list = PauliList(pauli_labels)

# Choose grouping based on commutativity type
if self.commuting_type == CommutingTypes.QUBITWISE:
grouped = pauli_list.group_qubit_wise_commuting()
else:
grouped = pauli_list.group_commuting()

grouped_monomials = [
[
PauliString.from_str(
mono.to_label() # pyright: ignore[reportAttributeAccessIssue]
)
for mono in pauli
]
for pauli in grouped
]

return grouped_monomials # pyright: ignore[reportReturnType]
else:
raise NotImplementedError(f"{self.grouping_method} is not yet supported.")

Expand Down
Loading
Loading