Skip to content
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

Implements partial substitution of Mul objects #1395

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

eeshan9815
Copy link
Contributor

Fixes #1359
Added 11 test cases which demonstrate the partial substitution of Mul in mixed-variable terms as well.
ping @isuruf

@isuruf-bot
Copy link

Hi,

I've run clang-format and found that the code needs formatting.
Here's a commit that fixes this. isuruf-bot@47616f0

To use the commit you can do

curl -o format.diff https://github.com/isuruf-bot/symengine/commit/47616f0b062d66db394f188d633a3fa70444a07c.diff
git apply format.diff

@ShikharJ
Copy link
Member

ShikharJ commented Feb 7, 2018

@eeshan9815 You can run ./bin/test_format_local.sh before committing the changes. That would automatically format the code.

@eeshan9815
Copy link
Contributor Author

@ShikharJ Okay, thanks!

@eeshan9815
Copy link
Contributor Author

@isuruf can you please review the PR?

symengine/subs.h Outdated
}
} else
d = x.get_dict();
} else if (is_a<Pow>(*sub1)) {
Copy link
Member

@isuruf isuruf Feb 8, 2018

Choose a reason for hiding this comment

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

This is handled in the first part. Why check again?

Copy link
Contributor Author

@eeshan9815 eeshan9815 Feb 9, 2018

Choose a reason for hiding this comment

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

@isuruf
The first part is the earlier implementation that only looks for exact matches, and not partial matches which should be handled using subs.
That part is retained only for the fast execution speeds in case of exact matches as it doesn't involve many heavy computations.

@isuruf
Copy link
Member

isuruf commented Feb 8, 2018

Here's some test cases to handle,

In [14]: t = 2*x* y * z * w

In [15]: t.subs({x*y: 2,z*w:4})
Out[15]: 16

In [16]: t.subs({x*y: 2,z:1})
Out[16]: 4*w

In [17]: t.subs({2*x*y: 5,2*z*w:3})
Out[17]: 3*x*y

In [18]: t.subs({2*x*y: 5,z*w:3})
Out[18]: 15

@eeshan9815
Copy link
Contributor Author

In [17]: t.subs({2*x*y: 5,2*z*w:3})
Out[17]: 3*x*y

How should it be decided whether 3*x*y is returned or 5*z*w?

@isuruf
Copy link
Member

isuruf commented Feb 8, 2018

How should it be decided whether 3xy is returned or 5zw?

Doesn't matter, use the first match.

@eeshan9815
Copy link
Contributor Author

Here's some test cases to handle,
In [14]: t = 2*x* y * z * w

In [15]: t.subs({x*y: 2,z*w:4})
Out[15]: 16

In [16]: t.subs({x*y: 2,z:1})
Out[16]: 4*w

In [17]: t.subs({2*x*y: 5,2*z*w:3})
Out[17]: 5*z*w

In [18]: t.subs({2*x*y: 5,z*w:3})
Out[18]: 15

I have added the above test cases to test_subs.cpp and all test cases are passing.
([17] matches to 5\*z\*w, not 3\*x\*y)

@eeshan9815
Copy link
Contributor Author

ping @isuruf

}
} else
d = x.get_dict();
} else if (is_a<Symbol>(*sub1)) {
Copy link
Member

Choose a reason for hiding this comment

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

Can you explain this part? Why is sub1 being a Symbol important? I thought the issue was that sub1 being a Mul isn't handled correctly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Partial substitution can happen for Symbol objects as well. For example, if the expression is x**2*y and sub1 is x, there is still partial substitution possible.
The first part only looks for exact matches.

Follow up question, should substitution happen repeatedly until not possible? For instance, if the expression is x**2*y**3 and x*y is to be replaced by z, should the result be x*y**2*z or y*z**2?

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, (x**2*y).subs({x: z}) didn't work before?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It did, but I've made the non fast_exec implementation complete. Should I remove these redundant parts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ping @isuruf

Copy link
Member

Choose a reason for hiding this comment

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

If it's redundant, remove them

Copy link
Member

Choose a reason for hiding this comment

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

@eeshan9815, sorry about the delay. Can you remove redundant code here?

@certik
Copy link
Contributor

certik commented Mar 6, 2018

Does this PR affect performance?

@eeshan9815
Copy link
Contributor Author

eeshan9815 commented Mar 7, 2018

@certik It is slower than the earlier implementation because that only naively looked at the expression for exact matches.
I have optimised the partial substitution part of the function by comparing and checking if the exponent of the expression to be substituted is smaller than that of the original expression rather than checking for exact matches of all the possibilities.
Also, if an exact match is found, it will be run as fast as the earlier implementation.

@eeshan9815
Copy link
Contributor Author

@isuruf is there more work to be done before merging?

@eeshan9815
Copy link
Contributor Author

ping @isuruf

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.

None yet

5 participants