Skip to content

Conversation

@dlyongemallo
Copy link
Contributor

Fixes #380.

Copilot AI review requested due to automatic review settings January 31, 2026 11:47
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes issue #380 by implementing proper handling of complex phases in the .to_adjoint() and .conjugate() methods across the PyZX codebase. Previously, these methods simply negated phases, which is incorrect for complex-valued phases that can arise in symbolic computations.

Changes:

  • Added Poly.conjugate() method to properly conjugate complex coefficients in polynomials
  • Updated Scalar.copy() to handle complex phases using (-phase).conjugate() transformation
  • Modified Gate.to_adjoint() to apply the same transformation for complex Poly phases
  • Added comprehensive test coverage for all three components

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pyzx/symbolic.py Adds conjugate() method to Poly class that conjugates complex coefficients while preserving real coefficients
pyzx/graph/scalar.py Updates copy() method with helper function to properly conjugate complex phases in all scalar fields
pyzx/circuit/gates.py Modifies to_adjoint() to detect Poly phases and apply (-phase).conjugate() transformation
tests/test_symbolic_parsing.py Adds test class with coverage for real, complex, and pure imaginary polynomial coefficients
tests/test_scalar.py Adds tests for scalar conjugation with complex phases in phase, phasenodes, and sum_of_phases
tests/test_circuit.py Adds tests for gate adjoint operations with real, symbolic, and complex phases

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

g.phase = -g.phase
phase = g.phase
if isinstance(phase, Poly):
g.phase = (-phase).conjugate()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this make sense? It looks like you are conjugating twice

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't understand. To compute the adjoint of e^{i π phase}, we need e^{-i π phase*} where phase* is the complex conjugate of phase. So (-phase).conjugate() is the correct value, isn't it?

Is the brackets that's the problem? Since negation and conjugation commute, I can remove them.

"""
def conjugate_phase(phase: FractionLike) -> FractionLike:
if isinstance(phase, Poly):
return (-phase).conjugate()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here, it looks like you are conjugating twice

Copy link
Collaborator

@jvdwetering jvdwetering left a comment

Choose a reason for hiding this comment

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

I'm a little bit confused about certain lines where it looks like you are conjugating the value twice. Could you take a look?

@dlyongemallo dlyongemallo force-pushed the 380-complex_phase_adjoint branch from 7fd77a2 to 210a4d2 Compare February 5, 2026 15:42
@dlyongemallo
Copy link
Contributor Author

I think I encountered a bug while trying to write a test for this. In these lines from symbolic.py, terms with complex coefficients are filtered out when doing the mod operation.

In set_phase it does a phase % 2 here, terms with complex coefficients are all dropped. Surely this is wrong?

@dlyongemallo
Copy link
Contributor Author

Ah, that was noticed in #377 already, but for multigraph.py.

@dlyongemallo dlyongemallo force-pushed the 380-complex_phase_adjoint branch from 86340ff to bcda7f9 Compare February 6, 2026 18:52
@dlyongemallo dlyongemallo force-pushed the 380-complex_phase_adjoint branch from bcda7f9 to 21b6f04 Compare February 6, 2026 19:02
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.

Incomplete handling of complex phases in .to_adjoint()

2 participants