Skip to content

Add support for Python 3.13 #836

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Mar 24, 2025

Conversation

edoaltamura
Copy link
Collaborator

This update introduces support for Python 3.13, scheduled for final release on 7 October 2024.

Closes #825
Closes OkuyanBoga#45

@edoaltamura edoaltamura added the type: ci 🔧 Related to Continuous Integration workflows label Oct 3, 2024
@edoaltamura edoaltamura marked this pull request as draft October 3, 2024 13:47
@edoaltamura edoaltamura marked this pull request as ready for review October 8, 2024 08:52
@woodsp-ibm
Copy link
Member

woodsp-ibm commented Oct 11, 2024

FYI: Qiskit 1.3.0 milestone, due by November 21, 2024

@edoaltamura edoaltamura added this to the 0.9.0 milestone Oct 18, 2024
@edoaltamura edoaltamura marked this pull request as draft October 18, 2024 14:45
@edoaltamura edoaltamura marked this pull request as ready for review November 6, 2024 16:44
@edoaltamura
Copy link
Collaborator Author

Un-drafting this PR ahead of the RC expected release date of Qiskit 1.3 (7 Nov 2024). The due date for the official release remains 21 Nov, which is when we expect to sync Python 3.13 support for Qiskit ML too.

@edoaltamura edoaltamura modified the milestones: 0.9.0, 0.8.1 Nov 11, 2024
@edoaltamura edoaltamura added the stable backport potential The bug might be minimal and/or import enough to be port to stable label Nov 12, 2024
@edoaltamura
Copy link
Collaborator Author

This PR has to be put on hold until #863 is resolved.

@edoaltamura edoaltamura added the on hold 🛑 Can not fix yet label Dec 2, 2024
@edoaltamura edoaltamura removed the on hold 🛑 Can not fix yet label Dec 16, 2024
edoaltamura and others added 2 commits March 19, 2025 12:23
Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com>
@edoaltamura
Copy link
Collaborator Author

Thanks very much @woodsp-ibm! I added the __eq__ functions to the optimizers to reflect those in Algos.

@edoaltamura edoaltamura removed the stable backport potential The bug might be minimal and/or import enough to be port to stable label Mar 19, 2025
@woodsp-ibm
Copy link
Member

I see my eq change failed with mypy - as there are so many mypy issues now in qiskit algorithms I had disabled it there as an interim solution so I had not seen that. Presumably if the object instance type is checked why would it not return False if its another type in this case rather than NotImplemented as the suggestion.

@edoaltamura
Copy link
Collaborator Author

Note that mypy requires this construct def __eq__(self, other: object) -> bool:, so I changed the methods to

# Under Python 3.13 the auto-generated equal fails with an error around
    # using numpy all or any. See https://github.com/qiskit-community/qiskit-algorithms/pull/225
    # for further information. Hence, this custom function was added. The __eq__
    # method is supposed to accept any object. If you update the version of
    # mypy you're using, it'll print out a note recommending this code structure.
    def __eq__(self, other: object) -> bool:
        if not isinstance(other, OptimizerState):
            # If we return NotImplemented, Python will automatically try
            # running other.__eq__(self), in case 'other' knows what to do with
            # Person objects.
            return NotImplemented

        return (
            (
                self.x == other.x
                if isinstance(self.x, float)
                else (self.x.shape == other.x.shape and (self.x == other.x).all())
            )
            and self.fun == other.fun
            and self.jac == other.jac
            and self.nfev == other.nfev
            and self.njev == other.njev
            and self.nit == other.nit
        )

and

# See parent class for a comment on having a custom equals. I needed this
    # too as it does not appear to use super by default and without this failed
    # the exact same way. Note it does not include learning rate as that field
    # is not included in the compare as pre the field decorator. The __eq__
    # method is supposed to accept any object. If you update the version of
    # mypy you're using, it'll print out a note recommending this code
    # structure.
    def __eq__(self, other: object) -> bool:
        if not isinstance(other, GradientDescentState):
            # If we return NotImplemented, Python will automatically try
            # running other.__eq__(self), in case 'other' knows what to do with
            # Person objects.
            return NotImplemented

        return super().__eq__(other) and self.stepsize == other.stepsize

You might find these useful for Algorithms too.

@woodsp-ibm
Copy link
Member

Thanks yes. I had already made a mental note to update algs with whatever worked here.

@woodsp-ibm
Copy link
Member

I am not sure why mypy is complaining now since that ternary was to do something different for float type such that it does not do the shape check etc

@edoaltamura
Copy link
Collaborator Author

Yeah I'm confused by mypy. It's basically forcing to cast many function declarations, and sometimes even confuses int for str.

mypy qiskit_machine_learning test tools
qiskit_machine_learning/state_fidelities/base_state_fidelity.py:312: error: Incompatible return value type (got "str | list[str] | list[list[str]] | list[list[list[Any]]]", expected "Sequence[float]")  [return-value]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("float" and "list[float]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("float" and "list[list[float]]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("float" and "list[list[list[Any]]]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: error: No overload variant of "__add__" of "list" matches argument type "float"  [operator]
qiskit_machine_learning/gradients/utils.py:107: note: Possible overload variants:
qiskit_machine_learning/gradients/utils.py:107: note:     def __add__(self, list[float], /) -> list[float]
qiskit_machine_learning/gradients/utils.py:107: note:     def [_S] __add__(self, list[_S], /) -> list[_S | float]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("list[float]" and "list[list[float]]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("list[float]" and "list[list[list[Any]]]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: note:     def __add__(self, list[list[float]], /) -> list[list[float]]
qiskit_machine_learning/gradients/utils.py:107: note:     def [_S] __add__(self, list[_S], /) -> list[_S | list[float]]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("list[list[float]]" and "list[float]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("list[list[float]]" and "list[list[list[Any]]]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: note:     def __add__(self, list[list[list[Any]]], /) -> list[list[list[Any]]]
qiskit_machine_learning/gradients/utils.py:107: note:     def [_S] __add__(self, list[_S], /) -> list[_S | list[list[Any]]]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("list[list[list[Any]]]" and "list[float]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: error: Unsupported operand types for + ("list[list[list[Any]]]" and "list[list[float]]")  [operator]
qiskit_machine_learning/gradients/utils.py:107: note: Both left and right operands are unions
qiskit_machine_learning/gradients/utils.py:107: error: Incompatible return value type (got "float | Any | list[float] | list[list[float]] | list[list[list[Any]]]", expected "list[ndarray[Any, Any]]")  [return-value]
qiskit_machine_learning/optimizers/steppable_optimizer.py:92: error: Item "float" of "float | ndarray[Any, Any]" has no attribute "shape"  [union-attr]
qiskit_machine_learning/optimizers/aqgd.py:170: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[Any]] | ndarray[tuple[int, ...], dtype[float64]]", variable has type "list[ndarray[tuple[int, ...], dtype[Any]] | ndarray[tuple[int, ...], dtype[float64]]]")  [assignment]
qiskit_machine_learning/optimizers/adam_amsgrad.py:187: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[Any]]", variable has type "ndarray[tuple[int], dtype[float64]]")  [assignment]
qiskit_machine_learning/optimizers/adam_amsgrad.py:189: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[Any]]", variable has type "ndarray[tuple[int], dtype[float64]]")  [assignment]
qiskit_machine_learning/optimizers/adam_amsgrad.py:190: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[Any]]", variable has type "ndarray[tuple[int], dtype[float64]]")  [assignment]
qiskit_machine_learning/optimizers/adam_amsgrad.py:216: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[float64]]", variable has type "ndarray[tuple[int], dtype[float64]]")  [assignment]
qiskit_machine_learning/optimizers/adam_amsgrad.py:217: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[float64]]", variable has type "ndarray[tuple[int], dtype[float64]]")  [assignment]
qiskit_machine_learning/optimizers/adam_amsgrad.py:219: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[float64]]", variable has type "ndarray[tuple[int], dtype[float64]]")  [assignment]
qiskit_machine_learning/optimizers/adam_amsgrad.py:234: error: Incompatible types in assignment (expression has type "ndarray[tuple[int, ...], dtype[Any]]", variable has type "ndarray[tuple[int], dtype[float64]]")  [assignment]
Found 21 errors in 5 files (checked 185 source files)

@woodsp-ibm
Copy link
Member

Is that mypy output from your local machine? Otherwise, as far as I can see, there is just the one issue its flagging in CI here - maybe locally you are not using the same versions as CI is.

@woodsp-ibm
Copy link
Member

woodsp-ibm commented Mar 19, 2025

For the mypy shape failure it seems my ternary expression had issues on closer inspection. I.e the first part said if both are float but it could then end up in the else where just one was a float, which evidently wont have shape. So it became a bit more complex and I updated the algs with the other mypy issue as well as fixing the shape aspect here qiskit-community/qiskit-algorithms#226 (it was failing with the mypy issue the same way locally but now passes locally with mypy for me though as I mentioned its disabled at present in algs since thats using a newer version of numpy - locally I still have a 2.0.2)

@edoaltamura
Copy link
Collaborator Author

It worked with the fix in Algorithms!

@coveralls
Copy link

Pull Request Test Coverage Report for Build 14001256542

Details

  • 6 of 8 (75.0%) changed or added relevant lines in 2 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.03%) to 90.828%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit_machine_learning/optimizers/gradient_descent.py 3 4 75.0%
qiskit_machine_learning/optimizers/steppable_optimizer.py 3 4 75.0%
Totals Coverage Status
Change from base Build 13973547049: -0.03%
Covered Lines: 4486
Relevant Lines: 4939

💛 - Coveralls

Copy link
Member

@woodsp-ibm woodsp-ibm left a comment

Choose a reason for hiding this comment

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

Just needs the branch rules updated then to remove the required 3.12 jobs no longer run and make the 3.13 ones, that superseded them, required,

@edoaltamura
Copy link
Collaborator Author

Thanks for approving the PR @woodsp-ibm! If I remember correctly, I cannot change the rules myself because only qiskit community members have those privileges. If this is still the case, could you please help with that?

@woodsp-ibm
Copy link
Member

woodsp-ibm commented Mar 24, 2025

@edoaltamura Ok I updated the rules for the main branch here. I will note in looking @smens has admin rights here in this repo and therefore should be able to do such a change too,

@edoaltamura edoaltamura merged commit 75e2109 into qiskit-community:main Mar 24, 2025
28 of 29 checks passed
@edoaltamura edoaltamura deleted the support-py313 branch March 24, 2025 13:52
@edoaltamura edoaltamura restored the support-py313 branch March 29, 2025 10:26
edoaltamura added a commit that referenced this pull request Apr 16, 2025
This was referenced May 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: ci 🔧 Related to Continuous Integration workflows
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add CI tests for py3.13 after final release #825 Add CI tests for py3.13 after final release
3 participants