Skip to content

Accept / in FreeParameterExpression string constructor #1251

@nilsquet

Description

@nilsquet

Accept / in FreeParameterExpression string constructor

The problem in one sentence

FreeParameterExpression("alpha/beta") raises ValueError: Unsupported binary operation: <class 'ast.Div'>, even though FreeParameter("alpha") / FreeParameter("beta") works fine.

What that looks like

from braket.parametric import FreeParameter, FreeParameterExpression
FreeParameter("alpha") / FreeParameter("beta")      # OK
FreeParameterExpression("alpha/beta")               # string path: raises ValueError

Both lines describe the same mathematical object. One builds it via Python's / operator; the other asks FreeParameterExpression to parse a string. They should produce the same result. They don't.

Why it matters: qiskit-braket-provider#153

The string path is not hypothetical. It's the path qiskit-braket-provider takes when converting a Qiskit ParameterExpression into a Braket FreeParameterExpression. The relevant code is in adapter.py:

def rename_parameter(parameter: Parameter) -> str:
    return str(parameter).replace("[", "_").replace("]", "")

...

case ParameterExpression():
    params[i] = FreeParameterExpression(rename_parameter(param))

So this perfectly reasonable Qiskit program:

from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit_braket_provider.providers.adapter import to_braket

x, y = Parameter("x"), Parameter("y")
qc = QuantumCircuit(1)
qc.rx(x / y, 0)

to_braket(qc)
# ValueError: Unsupported binary operation: <class 'ast.Div'>

...fails. And has been failing since qiskit-braket-provider#153 was filed.

Why this looks already fixed, but isn't

PR #885 (Feb 2024) added __truediv__ / __rtruediv__ operator methods to FreeParameterExpression, linked to QBP#153, and was merged. But #885 only touched the Python operator path. The string parser path runs different code: _parse_string_expressionast.parse_eval_operation, which consults a whitelist dict _operations that was left unchanged.

The two paths are both public API and should agree. Today they don't.

Where to look

The relevant code is in src/braket/parametric/free_parameter_expression.py, specifically the _operations dict built in FreeParameterExpression.__init__ and its consumer _eval_operation.

The __truediv__ method already exists on the class (added in #885) — the fix is about connecting it to the string-parsing path.

Tests to add

Mirror the existing pattern in test/unit_tests/braket/parametric/test_free_parameter_expression.py. test_truediv and test_r_truediv cover the Python-operator path. Add a matching test for the string-constructor path that asserts the two produce equal expressions.

A small parametrized regression test that runs each basic operator through both construction paths and asserts they agree is also welcome — it prevents the two whitelists from drifting again in the future.

How to verify the fix locally

git clone https://github.com/amazon-braket/amazon-braket-sdk-python.git
cd amazon-braket-sdk-python
pip install -e .
pytest test/unit_tests/braket/parametric/test_free_parameter_expression.py -v

All existing tests should pass alongside the new ones.

Definition of done

  • FreeParameterExpression("alpha/beta") constructs successfully and is equal to FreeParameter("alpha") / FreeParameter("beta").
  • The QBP reproducer above (to_braket(qc) with rx(x / y, 0)) succeeds.
  • New test covering the string-constructor path for division.
  • Existing test suite still passes.
  • CHANGELOG.md bug-fix entry referencing QBP#153.

uH 2026

Please note that we're still waiting for Unitary Foundation to review and approve our issues, so these are subject to change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions