Skip to content

Perf multiple circuit run for one job - #197

Draft
JulienCalistoTD wants to merge 44 commits into
devfrom
perf-multiple-circuit-run
Draft

Perf multiple circuit run for one job#197
JulienCalistoTD wants to merge 44 commits into
devfrom
perf-multiple-circuit-run

Conversation

@JulienCalistoTD

@JulienCalistoTD JulienCalistoTD commented May 6, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

@JulienCalistoTD JulienCalistoTD changed the title feat: enhance IBM execution to support multiple jobs and diagonal obs… perf: multiple circuit run for one job May 7, 2026
@JulienCalistoTD JulienCalistoTD changed the title perf: multiple circuit run for one job Perf multiple circuit run for one job May 7, 2026
@JulienCalistoTD

Copy link
Copy Markdown
Collaborator Author

transform jobs to single job but with multiple circuits

JulienCalistoTD and others added 25 commits June 3, 2026 17:30
…d execution

Co-authored-by: Copilot <copilot@github.com>
- Updated Job class to accept both QCircuit and CircuitBinding types for circuits.
- Enhanced compute_expectation_value to support CircuitBinding and handle multiple contexts.
- Modified run_ibm to streamline job execution for both single and multiple jobs.
- Adjusted measure handling in the runner to accommodate CircuitBinding.
- Added comprehensive tests for CircuitBinding in various modes (PRODUCT, ZIP, recursive).
- Improved error handling and validation for job compatibility with devices.
- Refactored run_aer to support CircuitBinding and ensure proper execution flow.
"""Returns if the matrix is already set in the observable."""
return not self._matrix is None

def is_pauli(self):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would rename the function is_pauli or is_matrix which can be misleading. Maybe is_matrix_set / is_pauli_string_set can do the job?

from qiskit.quantum_info import SparsePauliOp
from sympy import Basic, Expr

Coef = Union[Real, float, Expr, Basic]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe move this to mpqp.tools.generics ?
Or at least not put it in TYPE_CHECKING so it can be used in isinstance

from sympy import Expr

assert isinstance(
other, (int, float, complex, Expr)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can't directly use Coef here? I remember we already had this discussion/issue for Matrix, but in principle if Coef is also a Union of types, it should be able to check it

Comment thread mpqp/core/circuit.py
Comment on lines +1837 to +1852
@property
def job_type(self) -> "JobType":
"""
Returns the type of job associated with the circuit based on its measurements.
"""
from mpqp.execution.job import JobType

for measurement in self.measurements:
if isinstance(measurement, BasisMeasure):
if measurement.shots <= 0:
return JobType.STATE_VECTOR
else:
return JobType.SAMPLE
elif isinstance(measurement, ExpectationMeasure):
return JobType.OBSERVABLE
return JobType.STATE_VECTOR

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Note for me: double check that this is used in generate_jobs when we call run, to no do the same job twice

Comment thread mpqp/core/circuit.py
Comment on lines +1990 to +1996
class BindingMode(Enum):
PRODUCT = auto()
ZIP = auto()


class CircuitBinding:
def __init__(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would have put it in another file than circuit.py, if it doesn't imply circular dependencies

Comment thread mpqp/core/circuit.py
values: Optional[OneOrMany[dict[Expr | str, Complex | float]]] = None,
measurements: Optional[OneOrMany[Measure]] = None,
mode: BindingMode = BindingMode.PRODUCT,
noises: Optional[list[NoiseModel]] = None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This also be combined with product/zip (different noise models for different circuits/values/measurements?) ? If not then maybe just use the one attached to the QCircuit, I don't see why would we need to put it as a separate parameter

Comment thread mpqp/core/circuit.py
measurements: Optional[OneOrMany[Measure]] = None,
mode: BindingMode = BindingMode.PRODUCT,
noises: Optional[list[NoiseModel]] = None,
shots: Optional[int] = None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same remark for the shots, in principle they should be already informed in the Measure.

Comment thread mpqp/core/circuit.py
ZIP = auto()


class CircuitBinding:

@hJaffaliColibritd hJaffaliColibritd Aug 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Documentation, with examples

Comment thread mpqp/core/circuit.py
return params


class BindingMode(Enum):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Documentation

Comment thread mpqp/core/circuit.py
Optional["Measure"],
]
]:
"""Resolves the lazy execution graph and returns a flat list of

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Better documentation

Comment thread mpqp/core/circuit.py Outdated
Comment on lines +2222 to +2228
def merge_vals(v_base, v_curr):
if v_base is None and v_curr is None:
return None
merged = dict(v_base) if v_base is not None else {}
if v_curr is not None:
merged.update(v_curr)
return merged

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could be moved to tools? why defined inside the method ?

Comment thread mpqp/core/circuit.py
) -> "CircuitBinding": ...
def to_other_device(
self, device: AvailableDevice, programSet: bool = True
) -> "CircuitBinding | tuple[ProgramSet, list[tuple[Any]]] | list[tuple[EstimatorPubLike, Job]]":

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe use same organization as we recently did. Move this to mpqp.translation and call it from here ?

Comment on lines +202 to +212
for j in range(len(grouping)):
result = task[index][0]
for name, eigenvalue in eigenvalues.items():
for i in range(length):
binary_state = f"{bin(i)[2:].zfill(len(bin(length))- 3)}"
if binary_state in result.probabilities:
sorted_values[i] = result.probabilities[
binary_state
].real
else:
sorted_values[i] = 0

@hJaffaliColibritd hJaffaliColibritd Aug 21, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All the grouping thing I would create another method to handle that, for circuit biding or not circuit biding, and even I would say braket or not braket, because it is a general process that can be reused, right ?
Otherwise we will have as much implementations of the pauli grouping as providers and as ways to run circuits with observables (run normal, run binded, etc)

To be discussed

Comment thread mpqp/execution/job.py
"""Optional message associated with the current job status, especially
for execution errors."""

"""Store the measurement of a circuit."""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this is more used for circuit biding right ?

Comment thread mpqp/execution/job.py
"""Store the measurement of a circuit."""
self.measurement = measurement

"""Store parameters in case the original circuit was parametrized."""

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Or maybe say defined by symbolic parameters

Comment thread mpqp/execution/job.py
Comment on lines +145 to +146
if isinstance(self.circuit, CircuitBinding):
return None

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

here you would return self.measurement in the case of a CircutBiding no ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants