Skip to content

Feat cirq custom gate#200

Open
MathieuG-Colibri wants to merge 11 commits into
devfrom
feat-cirq-custom-gate
Open

Feat cirq custom gate#200
MathieuG-Colibri wants to merge 11 commits into
devfrom
feat-cirq-custom-gate

Conversation

@MathieuG-Colibri

Copy link
Copy Markdown
Collaborator

Change the cirq custom gate implem and behavior
Cleanup and bug fixing

Refactored to_other_language

@github-actions github-actions Bot added the enhancement New feature or request label May 20, 2026
@MathieuG-Colibri MathieuG-Colibri marked this pull request as ready for review June 17, 2026 08:25
@MathieuG-Colibri MathieuG-Colibri self-assigned this Jun 17, 2026
Comment on lines +37 to +43
┌──────────┐
q_0: ┤2 ├
│ │
q_1: ┤1 Unitary ├
│ │
q_2: ┤0 ├
└──────────┘

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 looks like a regression to me: previous version seemed more representative

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes but it made that we couldn't translate them back (cannot decompose into qasm).

So it had translatability issues.

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.

there is a difference between display and what's actually stored, see this comment: #200 (comment)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

done with print option df88af6

Comment thread mpqp/tools/cirq.py
from typing import Any, Optional

from mpqp.environment.var_cache import (
_INSTALLED_MPQP_PROVIDERS, # pyright: ignore[reportPrivateUsage]

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.

is there a reason to have it private ? I don't remember

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I don't know either I just know it was done that way before.

Comment thread mpqp/tools/unitary_decomposition.py Outdated
Comment on lines +70 to +71
if not is_unitary(v):
v = closest_unitary(v)

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 could move this test in "clostest_unitary"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

done df88af6

Comment thread mpqp/tools/unitary_decomposition.py Outdated
circuit.add(rotation(angle, position))
circuit.add(CNOT(control + position, position))
circuit.add(rotation(angle, int(targets[position])))
circuit.add(CNOT(int(control + targets[position]), int(targets[position])))

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.

why int casting ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It was a bug with a test where the typing got messed up here and it broken when adding gates.
So it's a failsafe that I put here because I never saw it happen anywhere else.

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 we should rather fix the test ?

Comment thread mpqp/tools/unitary_decomposition.py Outdated

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.

not part of the PR but not super clear

changed = _gray_code(i) ^ _gray_code(i + 1)
control = next(i for i in range(len(thetas)) if (changed >> i & 1))
control = max(-control - position - 1 + circuit.nb_qubits, 1)
control = max(-control - targets[position] - 1 + circuit.nb_qubits, 1)

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.

linked to previous comment

Comment thread mpqp/tools/unitary_decomposition.py Outdated
Comment on lines +152 to +155
if abs >= 1:
beta = 0
else:
beta = 2 * math.acos(abs)

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.

small preference for ternary here but you can ignore this comment if you will

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

done df88af6

Comment thread mpqp/tools/unitary_decomposition.py Outdated
Comment on lines +159 to +161
circuit.add(Rz(alpha, int(targets[position])))
circuit.add(Ry(beta, int(targets[position])))
circuit.add(Rz(gamma, int(targets[position])))

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 as before, why the int casting ? targets is supposed to be a list of ints

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

removed all int casting df88af6

The issue seems to be fixed

Comment thread tests/execution/test_validity.py Outdated
Comment thread tests/execution/test_validity.py
Comment thread mpqp/tools/cirq.py Outdated
InstalledProviders,
)

if InstalledProviders.BRAKET in _INSTALLED_MPQP_PROVIDERS:

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.

braket ? cirq ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

fixed df88af6

Comment thread mpqp/core/circuit.py

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.

moving the export to another file, why not, but maybe we should give it some more thought ? because as is we are duplicating some code for each supported language

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

My main reason for this change is that in some translation context we might need provider specific parameters that would be tougher to keep clean in one to_other_language function.

Comment thread mpqp/core/circuit.py Outdated

# This method adds a lot of identities so for a much cleaner circuit we remove them.
# Maybe add this as an option
c.instructions = [i for i in c.instructions if not isinstance(i, Id)]

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.

what are we doing with c ? it seems to me like we completely ignore it once built

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

refactored df88af6

Comment thread mpqp/tools/circuit.py
Comment on lines +385 to +387
# If the CustomControlledGate contains itself a custom gate it's better to return a bigger custom gate for compatibilities issues.
# If the non_controlled_gate is a NativeGate it shouldn't pose a problem.
# TODO: check how to decompose a ComposeGate that is inside a CCG, (example: a C-PRX)

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 have an exception for circuit drawing ? to solve the first comment I wrote in the PR

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

done df88af6

Comment thread mpqp/tools/circuit.py
return [gate]


def mpqp_to_qiskit(

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.

a inconvenient of moving the code here is that it makes the job of reviewing much trickier

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 we have a meeting to recap what changed ? it would save me some time ^^

@hJaffaliColibritd hJaffaliColibritd Jul 7, 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.

Maybe this was already discussed but I would like to know the reason why we would keep this here? (I take liberty to unresolve the comment)
I meen mpqp.tools.circuit is supposed to be for tools on manipulation of circuit. Anything related to translation should have another dedicated file/location in the code I believe

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.

@MathieuG-Colibri so my suggestion, as discussed this week, is to regroup all translation/conversion features and code in a new module/package mpqp.translationor whatever.
The idea is to regroup all specifc functions/block of code called in to_other_language and from_other_language, or other helper functions or tools related to translation. This should also include the package concerning qasm conversion, (we would typically now have mpqp.translation.qasm instead of mpqp.qasm for instance)

@MoHermes MoHermes self-requested a review July 1, 2026 09:24
Comment thread mpqp/tools/circuit.py

Note:
If the circuit contains ComposedGate type instructions you need to include the gate in the authorize_gates set for it to avoid decomposition, otherwise, the translation will always
try to use the gate's decomposition (see example). Also in the case of CustomGates it will always be decomposed into the {Ry, Rz, CNOT} basis for translation compatibilities.

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.

To update docs, we no longer decomposed into the {Ry, Rz, CNOT}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Solved (forgot which commit)

Comment thread mpqp/tools/circuit.py
for instruction in circuit.instructions:
if isinstance(instruction, (Measure, Breakpoint)):
continue
options = {"printing": printing} if isinstance(instruction, CustomGate) else {}

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.

So, printing=True apply only when the instruction is CustomGate?, I mean it is also propagated CustomControlledGate(...)?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes printing was used at the beginning to make sure we could print parametrized CG, I did something similar with Custom Controlled Gates.

if isinstance(gate, Operator):
gate = gate.to_instruction()
gate = gate.control(len(self.controls))
gate.control()

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.

Is this call intentional?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Removed 330e580

return UnitaryGate(self.matrix)
dummy_circuit.id(0)
return dummy_circuit.to_gate(
label=f"CustomGate({', '.join([str(s) for s in gate_symbols])})"

@hJaffaliColibritd hJaffaliColibritd Jul 4, 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.

Why did we change to this? the previous way of generating the label was not taking into account all the gate symbols?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes I think the issue was that not all the params were displayed.

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.

Is there a risk, when we have too much parameters, that the display become weird ? in that case we can put "..." and not list them all but the first and last.
If this never happens you can resolve this comment


return quantum_shannon_decomposition(self.matrix)
# non ordered targets
if any(

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.

raise a warning or something in this case?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Is it necessary to raise a warning if the edge case is taken into account anyway ?

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.

It's taken into account by tweaking the user's input, which may affect few stuff between what he submitted and what is actually run on the backend, right?
In that case it is nice if we can inform, or warn the user of the changes we make.

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

Labels

enhancement New feature or request testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants