Skip to content

MAINT: Make output of Polynomial representations consistent #21760

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 3 commits into from
Mar 7, 2024

Conversation

eendebakpt
Copy link
Contributor

@eendebakpt eendebakpt commented Jun 14, 2022

This is a followup from #21653 and #21654. In this PR we make the output of Polynomial.__str__ and Polynomial._repr_latex_ consistent. The representation for str now includes the domain-window mapping, which was hidden before.

Input

import numpy as np
x = np.arange(10)
y = 5 * x + 1 + .1*x*x-.1*x*x*x
f = np.polynomial.Polynomial.fit(x, y, 1)

print(str(f))
print(f._repr_latex_())

np.set_printoptions(precision=2)
print(str(f))
print(f._repr_latex_())

Output before:

6.1 - 7.38 x
$x \mapsto \text{6.1} - \text{7.38}\,\left(\text{-1.0} + \text{0.22222222}x\right)$
6.1 - 7.38 x
$x \mapsto \text{6.1} - \text{7.38}\,\left(\text{-1.0} + \text{0.22}x\right)$

After:

6.1 - 7.38 (-1.0 + 0.22222222x)
$x \mapsto \text{6.1} - \text{7.38}\,\left(\text{-1.0} + \text{0.22222222}x\right)$
6.1 - 7.38 (-1.0 + 0.22x)
$x \mapsto \text{6.1} - \text{7.38}\,\left(\text{-1.0} + \text{0.22}x\right)$

@eendebakpt eendebakpt marked this pull request as draft June 14, 2022 20:51
@eendebakpt eendebakpt marked this pull request as ready for review June 14, 2022 21:33
@seberg
Copy link
Member

seberg commented Jun 15, 2022

@rossbar maybe you can have a look? @eendebakpt this change looks like it should get a basic tests.

@axil
Copy link
Contributor

axil commented Jun 16, 2022

I would also suggest adding \cdot in the LaTeX representation. Currently it is displayed in the str() but not in the display():

image

Basically instead of
image
it would display as
image

@axil
Copy link
Contributor

axil commented Jun 16, 2022

The necessary change is trivial:

diff --git a/numpy/polynomial/_polybase.py b/numpy/polynomial/_polybase.py
index 920377535..483068cb5 100644
--- a/numpy/polynomial/_polybase.py
+++ b/numpy/polynomial/_polybase.py
@@ -490,7 +490,7 @@ def _repr_latex_(self):
             if term_str == '1':
                 part = coef_str
             else:
-                part = rf"{coef_str}\,{term_str}"
+                part = rf"{coef_str}\cdot{term_str}"

             if c == 0:
                 part = mute(part)

I can take care of the tests if the change is approved.

@axil
Copy link
Contributor

axil commented Jun 16, 2022

Also in ascii mode:

>>> print(str(f))
23.98618858 + 23.21718647*(-1.0 + 0.22222222x) -
0.70392674*(-1.0 + 0.22222222x)**2 - 1.23554729*(-1.0 + 0.22222222x)**3
diff --git a/numpy/polynomial/polynomial.py b/numpy/polynomial/polynomial.py
index 8e2c6f002..2cb96ee5d 100644
--- a/numpy/polynomial/polynomial.py
+++ b/numpy/polynomial/polynomial.py
@@ -1520,9 +1520,9 @@ def _str_term_unicode(cls, i, arg_str):
     @staticmethod
     def _str_term_ascii(i, arg_str):
         if i == '1':
-            return f" {arg_str}"
+            return f"*{arg_str}"
         else:
-            return f" {arg_str}**{i}"
+            return f"*{arg_str}**{i}"

     @staticmethod
     def _repr_latex_term(i, arg_str, needs_parens):

@axil
Copy link
Contributor

axil commented Jun 16, 2022

Or maybe to be verbose about the '*' before 'x' as well

>>> print(str(f))
23.98618858 + 23.21718647*(-1.0 + 0.22222222*x) -
0.70392674*(-1.0 + 0.22222222*x)**2 - 1.23554729*(-1.0 + 0.22222222*x)**3

(in ascii mode only), so that after copy-paste it would be a valid python string that can be executed with no modifications.

@eendebakpt
Copy link
Contributor Author

@axil Personally, I do not have a strong opinion on whether to use a dot, asterisk or no multiplication symbol (in either latex or str). But I am a bit hesitant to make changes to the current implementation.

If there is consensus with another numpy dev I would be fine with making the changes. Or perhaps make quick poll on the numpy mailing list and decide which format to pick

@eendebakpt
Copy link
Contributor Author

@rossbar maybe you can have a look? @eendebakpt this change looks like it should get a basic tests.

Basic test was added.

@rossbar Could you have a look at this PR?

@seberg seberg added the 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes label Oct 19, 2022
@eendebakpt
Copy link
Contributor Author

@seberg Do you want me to write release notes for this PR? I guess it should be with the compatibility label.

@eendebakpt
Copy link
Contributor Author

@seberg @rossbar Release notes have been added. Let now if I can do anything else for the PR.

@InessaPawson InessaPawson added the triage review Issue/PR to be discussed at the next triage meeting label May 15, 2023
@seberg seberg requested a review from charris May 31, 2023 17:53
@seberg
Copy link
Member

seberg commented May 31, 2023

We discussed that in the triage meeting and decided that either @charris or @rossbar should just make a decision on the dot bikeshed :).

@InessaPawson InessaPawson added triaged Issue/PR that was discussed in a triage meeting and removed triage review Issue/PR to be discussed at the next triage meeting labels May 31, 2023
@eendebakpt
Copy link
Contributor Author

@charris or @rossbar, could one of you review this PR?

Copy link
Contributor

@rossbar rossbar left a comment

Choose a reason for hiding this comment

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

Sorry for the delay @eendebakpt , this LGTM, pending the minor note about whether inline annotations are preferred. Will merge once that's cleared up!

def _repr_latex_(self):
# get the scaled argument string to the basis functions
off, scale = self.mapparms()
def _format_term(self, scalar_format: Callable, off: float, scale: float):
Copy link
Contributor

Choose a reason for hiding this comment

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

AFAIK the policy is still to only include annotations in the pyi files - @seberg is this true?

Copy link
Member

Choose a reason for hiding this comment

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

Dunno, have seen other code with private annotations which I think these are.

Copy link
Contributor

Choose a reason for hiding this comment

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

If it doesn't matter then let's put it in, just wanted to make sure I wasn't missing any changes to the type annotation policies!

@rossbar rossbar merged commit a174433 into numpy:main Mar 7, 2024
@rgommers rgommers added this to the 2.0.0 release milestone Mar 7, 2024
@seberg
Copy link
Member

seberg commented Mar 7, 2024

@eendebakpt seems this created a merge conflict (failing tests). Any chance you can look into that?

@mattip
Copy link
Member

mattip commented Mar 7, 2024

I am seeing a new error after this was merged on some unrelated PR:

    def test_polynomial_str(self):
        res = str(poly.Polynomial([0, 1]))
        tgt = '0.0 + 1.0 x'
>       assert_equal(res, tgt)
E       AssertionError: 
E       Items are not equal:
E        ACTUAL: '0.0 + 1.0·x'
E        DESIRED: '0.0 + 1.0 x'

I wonder how this passed, maybe it was not merged to main first?

@eendebakpt
Copy link
Contributor Author

I will look into it

@eendebakpt
Copy link
Contributor Author

This PRwas merged without merging with main first it seems. The latest time CI was executed was 5 months ago, so that might explains why we see some errors now.

The ABCPolyBase has an attribute _use_unicode = not os.name == 'nt' that determines whether we can have the dot symbol in the represenation or not. The test from @mattip works if _use_unicode is False, but fails if _use_unicode is True.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
03 - Maintenance 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes triaged Issue/PR that was discussed in a triage meeting
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants