Skip to content

Conversation

@yaelbh
Copy link
Collaborator

@yaelbh yaelbh commented Nov 16, 2025

The executor does not accept parameter expressions. This PR provides a function that users can run before they instantiate a quantum program. The function will transform their circuit and parameter values such that parameter expressions are removed.

For the PR to be ready:

  • Build a table of parameter expressions, to avoid redundant creation of identical parameters.
  • Support multiple parameters in a gate.
  • Support dynamic circuits.
  • Check if boxes are supported, and fix if not.
  • Check if the case of one parameter in the entire circuit is supported, and fix if not.
  • Allow the user to control parameter names - I actually think this one is not needed, so I'm marking it as done although not done.
  • Save the time of parameter creation and binding when the parameter is of type Parameter.
  • Use bind_all instead of projecting and using bind.
  • Write tests.

@yaelbh yaelbh marked this pull request as draft November 16, 2025 09:24
@yaelbh yaelbh requested a review from SamFerracin November 17, 2025 13:16
@yaelbh
Copy link
Collaborator Author

yaelbh commented Nov 17, 2025

Note that, with the current implementation, some of the parameters and instructions are shared between the original and the generated circuits.

Copy link
Collaborator

@joshuasn joshuasn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you looked at samplomatic's ParameterExpressionTable? The logic for handling the parameter expressions is very similar to what you have here, it might be a good idea to use that so we don't have to support support two different implementations of the same thing.

Further, it also allows you to construct the parameter table without knowing the parameters, which could be useful on its own.

Copy link
Collaborator

@SamFerracin SamFerracin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, Yael!
I left a few comments. Additionally, I +1 Josh's comment that it would be nice to structure parameter handling exactly as in Samplomatic, which would make it easier to maintain



def _remove_parameter_expressions_in_blocks(
circ: QuantumCircuit,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
circ: QuantumCircuit,
circuit: QuantumCircuit,



def remove_parameter_expressions(
circ: QuantumCircuit, param_values: np.ndarray
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
circ: QuantumCircuit, param_values: np.ndarray
circuit: QuantumCircuit, param_values: np.ndarray

Comment on lines 88 to 89
"""Create an input to the quantum program that's
free from parameter expressions."""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Create an input to the quantum program that's
free from parameter expressions."""
"""A helper to replace a circuit's parameter expressions with parameters."""

This is a function on circuits, not on programs or program items. Also, more than removing stuff, we replace stuff, so consider using replace_* instead of remove_*

Additionally, I would expand a bit the docstring, to add a short explanation of what we do, how we recurse into conditionals, and how we transform the parameter values.

parameter_table: dict[str, Parameter] = {}
new_param_value_cols: list[np.ndarray] = []

new_circ = _remove_parameter_expressions_in_blocks(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "_in_blocks" part of _remove_parameter_expressions_in_blocks here is a bit confusing, because the circuit may not have any blocks. For readability, I would consider removing "_in_blocks" and calling it _remove_parameter_expressions

Comment on lines +39 to +45
param_values = np.array(
[
[[1, 2], [3, 4], [5, 6], [7, 8]],
[[9, 10], [11, 12], [13, 14], [15, 16]],
[[17, 18], [19, 20], [21, 22], [23, 24]],
]
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
param_values = np.array(
[
[[1, 2], [3, 4], [5, 6], [7, 8]],
[[9, 10], [11, 12], [13, 14], [15, 16]],
[[17, 18], [19, 20], [21, 22], [23, 24]],
]
)
param_values = np.arange(1, 25).reshape((3, 4, 2))

Generally, the params will be floats. Therefore, I would actually favour something like this:

Suggested change
param_values = np.array(
[
[[1, 2], [3, 4], [5, 6], [7, 8]],
[[9, 10], [11, 12], [13, 14], [15, 16]],
[[17, 18], [19, 20], [21, 22], [23, 24]],
]
)
param_values = np.random.random((3, 4, 2))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it more readable if the array is written explicitly. How about keeping the original array, and only adding dtype=float?

@ElePT ElePT added the executor-preview Issues related to the `executor_preview` branch label Nov 18, 2025
@yaelbh
Copy link
Collaborator Author

yaelbh commented Nov 19, 2025

I'm taking back what I said in the standup today, switching to samplomatic's parameter table only simplifies.

@yaelbh yaelbh changed the title [WIP] A function to remove parameter expressions A function to remove parameter expressions Nov 20, 2025
@yaelbh yaelbh marked this pull request as ready for review November 20, 2025 16:16
@ihincks ihincks changed the title A function to remove parameter expressions [executor] A function to remove parameter expressions Nov 20, 2025
Comment on lines +80 to +81
The function tranverses the circuit and collects all the parameters and parameter expressions.
A new parameter is created for every parameter expression that is not a parameter.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that you shouldn't worry about replacing only the parameter expressions.

Suggested change
The function tranverses the circuit and collects all the parameters and parameter expressions.
A new parameter is created for every parameter expression that is not a parameter.
The function tranverses the circuit and replaces all the parameters and parameter expressions with new parameters.

This would allow you to simplify massively this function (no need for parameter_expressions_to_new_parameters_map) and to make a more standard use of the parameter table where you simply:

  1. Append every parameter/parameter expression you find to it
  2. Call evaluate at the end

If there are some concerns that are missing, we should improve the parameter expression table directly, rather than writing more code in places where we use it (cc'in @joshuasn here, as he's the one who wrote the table in the first place)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still need parameter_expressions_to_new_parameters_map, because the same parameter / parameter expression can appear several times in a circuit. So, if a+b appears 100 times, I want to create one parameter; later when I see a+b in my circuit I want to know with which parameter to replace it, and I do it by querying the map.

@yaelbh yaelbh requested a review from SamFerracin November 23, 2025 06:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

executor-preview Issues related to the `executor_preview` branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants