Skip to content

[CQT-59] implement SGMQ notation in the CircuitBuilder#675

Open
rares1609 wants to merge 1 commit intodevelopfrom
CQT-59-Implement-SGMQ-notation-in-the-circuit-builder
Open

[CQT-59] implement SGMQ notation in the CircuitBuilder#675
rares1609 wants to merge 1 commit intodevelopfrom
CQT-59-Implement-SGMQ-notation-in-the-circuit-builder

Conversation

@rares1609
Copy link
Copy Markdown
Contributor

No description provided.

@rares1609 rares1609 requested a review from elenbaasc March 30, 2026 10:03
Copy link
Copy Markdown
Collaborator

@elenbaasc elenbaasc left a comment

Choose a reason for hiding this comment

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

There are many helper functions that have been added to the CircuitBuilder, that are in my opinion overkill. For two qubit gates and the measure instruction we only allow for operand lists of equal lengths (and no tuple style SGMQ notation).

Try to simplify the (added) code significantly. Also, private helper functions shouldn't have doc-strings.

Comment on lines +519 to +524
def test_sgmq_cnot_from_list(self) -> None:
builder = CircuitBuilder(4)
builder.CNOT([0, 3], [1, 3], [2, 3])
circuit = builder.to_circuit()

assert circuit.ir.statements == [CNOT(0, 3), CNOT(1, 3), CNOT(2, 3)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is unwanted behaviour and should raise an error.
The CNOT instruction should only allow lists for the arguments (and there are only 2 input arguments).

The test should be:

Suggested change
def test_sgmq_cnot_from_list(self) -> None:
builder = CircuitBuilder(4)
builder.CNOT([0, 3], [1, 3], [2, 3])
circuit = builder.to_circuit()
assert circuit.ir.statements == [CNOT(0, 3), CNOT(1, 3), CNOT(2, 3)]
def test_sgmq_cnot_from_list(self) -> None:
builder = CircuitBuilder(4)
builder.CNOT([0, 1, 2], [3, 3, 3])
circuit = builder.to_circuit()
assert circuit.ir.statements == [CNOT(0, 3), CNOT(1, 3), CNOT(2, 3)]

Copy link
Copy Markdown
Contributor Author

@rares1609 rares1609 Mar 31, 2026

Choose a reason for hiding this comment

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

I understand the general comment that we do not want a tuple style SGMQ, and will remove this functionality. I thought it would be nice if we wanted to apply a two-qubit gate to multiple qubits, to have a one liner specifying a list of tuples with the control&target qubits for each applied gate.

I have a question to understand your vision a bit better. You are ok with having SGMQ for two qubit gates where there are two list arguments, the first lists specifying control qubits, and the second list target qubits?

And overall you would want to restrict SGMQ notation functionality solely to this format for two qubit gates?

Comment on lines +122 to +137
@staticmethod
def _is_sgmq_expandable(arg: Any) -> bool:
"""Check if an argument should be expanded for SGMQ notation.

An argument should be expanded if it is:
- A list (but not a tuple, which is used for axis arguments)
- A Register (QubitRegister or BitRegister) that is not being used as an index

Args:
arg: The argument to check.

Returns:
True if the argument should be expanded, False otherwise.

"""
return isinstance(arg, (Register, list))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is overkill for a simple isinstance statement.

Comment on lines +526 to +531
def test_sgmq_cnot_first_qubit_list(self) -> None:
builder = CircuitBuilder(4)
builder.CNOT([0, 1, 2], 3)
circuit = builder.to_circuit()

assert circuit.ir.statements == [CNOT(0, 3), CNOT(1, 3), CNOT(2, 3)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not permitted.

builder.add_register(controls)
builder.add_register(targets)

builder.CNOT(controls, targets[0])
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not permitted (just like measure, the length of the input arguments should match).

Comment on lines +551 to +556
def test_sgmq_cz_first_qubit_list(self) -> None:
builder = CircuitBuilder(3)
builder.CZ([0, 1], 2)
circuit = builder.to_circuit()

assert circuit.ir.statements == [CZ(0, 2), CZ(1, 2)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not permitted.

Comment on lines +572 to +580
def test_sgmq_two_qubit_gate_with_register_slice(self) -> None:
builder = CircuitBuilder()
q0 = QubitRegister(4, "q0")
builder.add_register(q0)

builder.CZ(q0[0:2], q0[3])
circuit = builder.to_circuit()

assert circuit.ir.statements == [CZ(0, 3), CZ(1, 3)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not permitted.


### Added

- Add Single Gate Multi Qubit (SGMQ) notation
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
- Add Single Gate Multi Qubit (SGMQ) notation
- Add Single Gate Multi Qubit (SGMQ) notation to the `CircuitBuilder`

if not args:
return [args]

expandable_indices = [i for i, arg in enumerate(args) if self._is_sgmq_expandable(arg)]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm not sure what is happening here?

Comment on lines +196 to +197
if self._is_tuple_style_sgmq(args):
return self._expand_tuple_style_args(args)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think we want this to be permitted. We should not allow for tuple style SQMG notation. Input (qu)bit arguments are singular, a list, or a Register.

def _expand_tuple_style_args(args: tuple[Any, ...]) -> list[tuple[Any, ...]]:
return [tuple(arg) for arg in args]

def _expand_measure_args(self, args: tuple[Any, ...], expandable_indices: list[int]) -> list[tuple[Any, ...]]:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The measure instruction should not require such a complex and specific method. For both the measure instruction and any two-qubit gate, the first two arguments are always the operands.

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.

2 participants