-
-
Notifications
You must be signed in to change notification settings - Fork 4.4k
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
Bug Fixed : Matrix power of identity matrix fails #9823 #9830
Conversation
I think this looks fine and is a nice addition, one peculiar inconsistency I noticed though:
i.e. for negative powers the |
Thanks for pointing that out @bjodah I will make the change and update the pull request. |
@bjodah @kevalds51 This problem also occurs with |
@kevalds51, @oliverlee and I just spoke. We can accept this PR instead of Oliver's but you need to fix the ZeroMatrix issue here too and add tests for it. Maybe see Oliver's PR for how he did it. |
@moorepants |
@moorepants I am getting this test_code_quality fail, can you suggest me on how to cope up with it. |
assert MatPow(l, 2).doit() == l | ||
assert MatPow(l, -1).doit() == l | ||
assert MatPow(l, 0).doit() == l | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have trailing spaces on this line. FYI you should run ./bin/test sympy/utilities/tests/test_code_quality.py
the output will tell you about the code quality issues.
Here's what I get
$ ./bin/test sympy/utilities/tests/test_code_quality.py
================================================================ test process starts =================================================================
executable: /home/leosartaj/projects/sympy/my/bin/python (2.7.10-final-0) [CPython]
architecture: 64-bit
cache: yes
ground types: python
random seed: 56687482
hash randomization: on (PYTHONHASHSEED=2022273946)
sympy/utilities/tests/test_code_quality.py[6] F..... [FAIL]
______________________________________________________________________________________________________________________________________________________
_______________________________________________ sympy/utilities/tests/test_code_quality.py:test_files ________________________________________________
File "/home/leosartaj/projects/sympy/sympy/utilities/tests/test_code_quality.py", line 228, in test_files
check_directory_tree(SYMPY_PATH, test, exclude)
File "/home/leosartaj/projects/sympy/sympy/utilities/tests/test_code_quality.py", line 107, in check_directory_tree
check_files(glob(join(root, pattern)), file_check, exclusions)
File "/home/leosartaj/projects/sympy/sympy/utilities/tests/test_code_quality.py", line 123, in check_files
file_check(fname)
File "/home/leosartaj/projects/sympy/sympy/utilities/tests/test_code_quality.py", line 146, in test
test_this_file(fname, test_file)
File "/home/leosartaj/projects/sympy/sympy/utilities/tests/test_code_quality.py", line 169, in test_this_file
assert False, message_space % (fname, idx + 1)
AssertionError: File contains trailing whitespace: /home/leosartaj/projects/sympy/sympy/matrices/expressions/tests/test_matpow.py, line 108.
================================================ tests finished: 5 passed, 1 failed, in 2.88 seconds =================================================
DO *NOT* COMMIT!
@moorepants Is this ok to be merged? can you please review this again and tell me. @leosartaj I appreciate it, that trailing space troubled me a lot earlier. |
@@ -70,7 +70,7 @@ def test_doit_square_MatrixSymbol_symsize(): | |||
|
|||
def test_doit_with_MatrixBase(): | |||
X = ImmutableMatrix([[1, 2], [3, 4]]) | |||
assert MatPow(X, 0).doit() == ImmutableMatrix(Identity(2)) | |||
assert MatPow(X, 0).doit().as_explicit() == ImmutableMatrix(Identity(2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the test changed? You shouldn't change a test unless it was testing against an incorrect solution.
You're new code should not affect existing tests (unless the tests were wrong), it should only need new tests added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@moorepants
I did it because ImmutableMatrix(Identity(2)) returns the matrix in explicit form. (So i guess the test is wrong.)
So inspite of ImmutableMatrix(Identity(2)), it can be just : Identity(2).
or we can just check the explicit form of LHS term
@oliverlee Can you review this since you thought about it more? |
We want any powers of Test functions names should use Also, I wasn't thinking when writing my tests, but the inverse of |
Should the 0'th power of |
It is here: sympy/sympy/matrices/expressions/matexpr.py Line 466 in 5578492
|
OK, that's what I had in mind. |
@oliverlee |
I don't understand why the most recent commit is failing, can anyone please help. |
This is probably due to #9846. This is fixed now. You should update your branch with the current master. |
@oliverlee @moorepants |
@@ -70,7 +70,7 @@ def test_doit_square_MatrixSymbol_symsize(): | |||
|
|||
def test_doit_with_MatrixBase(): | |||
X = ImmutableMatrix([[1, 2], [3, 4]]) | |||
assert MatPow(X, 0).doit() == ImmutableMatrix(Identity(2)) | |||
assert MatPow(X, 0).doit() == Identity(2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test shouldn't change. If you take an instance of ImmutableMatrix
to the zero power, you expect to get back an ImmutableMatrix
.
Other than that, looks fine to me. |
@oliverlee |
@kevalds51 Sure, and also revert changes to that one test case. I don't know how errors should be raised though. |
@oliverlee X = ImmutableMatrix([[1, 2], [3, 4]]) or X = ImmutableMatrix([[1, 2], [3, 4]]) Can you or @moorepants help me with this |
@kevalds51 Your patch always returns an instance of |
@oliverlee How about this? |
@bjodah can you please review this? |
@@ -110,7 +110,11 @@ def __rmul__(self, other): | |||
def __pow__(self, other): | |||
if not self.is_square: | |||
raise ShapeError("Power of non-square matrix %s" % self) | |||
if other is S.NegativeOne: | |||
if self.is_ZeroMatrix: | |||
return self |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to return the zero matrix for all powers while line 467 returns the identity for the 0th power of the zero matrix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jksuom That is because, zero matrix raised to any positive power is zero matrix itself, whereas zero matrix raised to power 0 is an Identity matrix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will the exponent other
be positive here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
If an instance of a zero matrix is raised to -ve power it will raise the value error saying matrix is invertible, as in : (ZeroMatrix(3,3))**-2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that ZeroMatrix.__pow__
already takes care of all powers of a ZeroMatrix
: zeroth, negative (could be if other < 0:
) and positive. Under which conditions would a ZeroMatrix
appear as an argument of MatrixExpr.__pow__
making this line necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After running a few checks, I agree to you that this line is redundant, I will make the changes as soon as possible.
Earlier I wasn't able to get you, sorry for the misunderstanding.
It's a PyPy issue. I have restarted the job. |
@jksuom All good now? |
@@ -465,6 +467,8 @@ def __pow__(self, other): | |||
raise ShapeError("Power of non-square matrix %s" % self) | |||
if other == 0: | |||
return Identity(self.rows) | |||
if other<1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
other<1
-> other < 1
, space needed
You can insert space at all other places as well, it makes the code more of readable. |
assert MatPow(l, 2).doit() == l | ||
assert MatPow(l, -1).doit() == l | ||
assert MatPow(l, 0).doit() == l | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more line here.
@kevalds51 you should take a look at this comment. |
@oliverlee You want to review this one more time? |
@moorepants does this look good? |
@@ -56,14 +56,25 @@ def doit(self, **kwargs): | |||
args = self.args | |||
base = args[0] | |||
exp = args[1] | |||
if isinstance(base, MatrixBase) and exp.is_number: | |||
if exp.is_zero and base.is_square: | |||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why you're using a try/catch statement to evaluate an object of instance MatrixBase
to the zero power. It's already defined here:
sympy/sympy/matrices/matrices.py
Line 521 in 19f5894
def __pow__(self, num): |
But it looks like all tests pass and this addresses the issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was done to deal with special cases, such as instances of Immutable matrix (being raised to power 0), where I have to return it in the form of base.class(Identity(base.shape[0])), and not just as Identity((base.shape[0])).
If not done so, there will be issues while dealing with Immutable matrix instance or other similar ones. (It did lead to assertion errors in test cases in previous commits)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't you check if it's an instance of MatrixBase
and calculate the result normally? There weren't any problems with that before so I don't see why that wouldn't work here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To solve the issue in the first place (for powers of both Identity and Zero Matrix), changes were made that required further adding of conditions.
Also there were other examples that gave wrong results for power zero (some were not tested in the test cases), to deal with that I had to add try/catch to return the proper instance.
I'm facing some problems in managing branches, so I'll be closing this pull request. @bjodah Should I create another request (this exact same one) after I fix the issues on my machine? |
@kevalds51, there really shouldn't be a need for you to open another pull request. If you do, the people who have reviewed this PR would have to go over everything again from scratch (or cross reference everything from the review here). More specifically, what troubles are you facing with git, maybe we can help? |
That would be great. I just got used to Git a few weeks back. |
I see. You should be able to do something along these lines:
EDIT: added fetch on row 2 |
Worked nicely, thanks |
@kevalds51 Any reason you closed this? |
I had pushed from master of my local repo, this also led to merge conflicts in new PRs. |
If we haven't gotten your work on this merged, we want to. You can open a new PR if you are having git issues. But in the future, ask us about the git issues and merge conflicts and we can help you solve them. |
Sure, it is settled once and for all. As of now, I'll open a new PR. |
Please refer to PR #9978 |
Added the test to exercise the code change. (as requested by the @moorepants )
Modified the code such that no error is generated for both MatPow method and ** operator.
removed extra blank line which resulted in test_code_quality fail.