Reformat pieces of expressions in SymPy to prevent distribution of constant coefficient
up vote
1
down vote
favorite
Suppose I define the following expression:
poly1 = 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
which prints out:
6/(25*x + 75) + 1/(5*(x + 3)**2)
I have two questions regarding this expression. Firstly, is there a way to keep the expression in the format in which I entered it? In particular, is there something that I could do in order to leave the denominator of the first term as 25*(x + 3)?
Secondly, if I have the expression in its printed form, what is the best way to break apart the expression, reformat the denominator of the first term, and then put it back together? Ideally I would be able to just dig into the expression using a series of args calls to get to the denominator of the first term, and then use the factor function to factor it properly, as in poly1.args[0].args[1].args[0].factor(). The problem is that, since the Tuples making up the expression are immutable, I can't just replace a piece of poly1 with the expression computed above. Is there a better way to substitute in the factored polynomial than just rebuilding the whole expression from scratch?
Note: I'd rather not use the subs() method, because that searches the entire expression, and it seems like there might be cases where you would want to be very specific about the different pieces you modify.
python sympy
add a comment |
up vote
1
down vote
favorite
Suppose I define the following expression:
poly1 = 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
which prints out:
6/(25*x + 75) + 1/(5*(x + 3)**2)
I have two questions regarding this expression. Firstly, is there a way to keep the expression in the format in which I entered it? In particular, is there something that I could do in order to leave the denominator of the first term as 25*(x + 3)?
Secondly, if I have the expression in its printed form, what is the best way to break apart the expression, reformat the denominator of the first term, and then put it back together? Ideally I would be able to just dig into the expression using a series of args calls to get to the denominator of the first term, and then use the factor function to factor it properly, as in poly1.args[0].args[1].args[0].factor(). The problem is that, since the Tuples making up the expression are immutable, I can't just replace a piece of poly1 with the expression computed above. Is there a better way to substitute in the factored polynomial than just rebuilding the whole expression from scratch?
Note: I'd rather not use the subs() method, because that searches the entire expression, and it seems like there might be cases where you would want to be very specific about the different pieces you modify.
python sympy
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
Suppose I define the following expression:
poly1 = 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
which prints out:
6/(25*x + 75) + 1/(5*(x + 3)**2)
I have two questions regarding this expression. Firstly, is there a way to keep the expression in the format in which I entered it? In particular, is there something that I could do in order to leave the denominator of the first term as 25*(x + 3)?
Secondly, if I have the expression in its printed form, what is the best way to break apart the expression, reformat the denominator of the first term, and then put it back together? Ideally I would be able to just dig into the expression using a series of args calls to get to the denominator of the first term, and then use the factor function to factor it properly, as in poly1.args[0].args[1].args[0].factor(). The problem is that, since the Tuples making up the expression are immutable, I can't just replace a piece of poly1 with the expression computed above. Is there a better way to substitute in the factored polynomial than just rebuilding the whole expression from scratch?
Note: I'd rather not use the subs() method, because that searches the entire expression, and it seems like there might be cases where you would want to be very specific about the different pieces you modify.
python sympy
Suppose I define the following expression:
poly1 = 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
which prints out:
6/(25*x + 75) + 1/(5*(x + 3)**2)
I have two questions regarding this expression. Firstly, is there a way to keep the expression in the format in which I entered it? In particular, is there something that I could do in order to leave the denominator of the first term as 25*(x + 3)?
Secondly, if I have the expression in its printed form, what is the best way to break apart the expression, reformat the denominator of the first term, and then put it back together? Ideally I would be able to just dig into the expression using a series of args calls to get to the denominator of the first term, and then use the factor function to factor it properly, as in poly1.args[0].args[1].args[0].factor(). The problem is that, since the Tuples making up the expression are immutable, I can't just replace a piece of poly1 with the expression computed above. Is there a better way to substitute in the factored polynomial than just rebuilding the whole expression from scratch?
Note: I'd rather not use the subs() method, because that searches the entire expression, and it seems like there might be cases where you would want to be very specific about the different pieces you modify.
python sympy
python sympy
edited Nov 10 at 23:44
user6655984
asked Nov 10 at 21:07
Lucas Myers
236
236
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
1
down vote
accepted
Automatic distribution of constants is a touchy subject. There is an option to disable it as follows:
from sympy.core.evaluate import distribute
with distribute(False):
poly1 = 6/(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or you can wrap 25 in UnevaluatedExpr to prevent its interaction with other terms.
poly1 = 6/(UnevaluatedExpr(25)*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6*25**(-1)/(x + 3) + 1/(5*(x + 3)**2)
Or use the un-evaluated product (Mul) in the denominator:
poly1 = 6/Mul(25, x+3, evaluate=False) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or wrap the denominator in factor_terms -- a gentler form of factor which does the job of extracting the coefficient without messing too much with the expression.
poly1 = 6/factor_terms(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or cheat by introducing a symbol that looks like a number:
c25 = symbols('25')
poly1 = 6/(c25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 1/(5*(x + 3)**2) + 6/(25*(x + 3))
Suggested reading: Prevent expression evaluation
The second question, about targeted replacement, is hard to answer in this generality. One has to recurse through the expression tree, rebuilding expr as expr.func(*args) where args are expr.args, possibly modified. The main issue is how you will know that this instance of 25*x + 75 is the one that should be replaced.
2
And that about covers it! Great summary of methods. As for the second question, take a look at the not-oft-mentioned traversaltools in simplify.
– smichr
Nov 11 at 18:50
@smichr, the documentation for traversaltools seems sparse, so just to clarify:use()applies some function to every argument at a given level on the expression tree? Is there a way to specify one particular node of the graph (i.e. one argument of the expression) to apply some function to? @Welcome to Stack Overflow, I'm looking for something like theReplacePartfunction from Mathematica -- something which replaces a given node on the expression graph, rather than recursing through the graph in order to search for something that matches a particular form.
– Lucas Myers
Nov 11 at 22:45
1
Sorry...I meantepathtoolsin the same folder.
– smichr
Nov 13 at 14:47
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
Automatic distribution of constants is a touchy subject. There is an option to disable it as follows:
from sympy.core.evaluate import distribute
with distribute(False):
poly1 = 6/(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or you can wrap 25 in UnevaluatedExpr to prevent its interaction with other terms.
poly1 = 6/(UnevaluatedExpr(25)*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6*25**(-1)/(x + 3) + 1/(5*(x + 3)**2)
Or use the un-evaluated product (Mul) in the denominator:
poly1 = 6/Mul(25, x+3, evaluate=False) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or wrap the denominator in factor_terms -- a gentler form of factor which does the job of extracting the coefficient without messing too much with the expression.
poly1 = 6/factor_terms(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or cheat by introducing a symbol that looks like a number:
c25 = symbols('25')
poly1 = 6/(c25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 1/(5*(x + 3)**2) + 6/(25*(x + 3))
Suggested reading: Prevent expression evaluation
The second question, about targeted replacement, is hard to answer in this generality. One has to recurse through the expression tree, rebuilding expr as expr.func(*args) where args are expr.args, possibly modified. The main issue is how you will know that this instance of 25*x + 75 is the one that should be replaced.
2
And that about covers it! Great summary of methods. As for the second question, take a look at the not-oft-mentioned traversaltools in simplify.
– smichr
Nov 11 at 18:50
@smichr, the documentation for traversaltools seems sparse, so just to clarify:use()applies some function to every argument at a given level on the expression tree? Is there a way to specify one particular node of the graph (i.e. one argument of the expression) to apply some function to? @Welcome to Stack Overflow, I'm looking for something like theReplacePartfunction from Mathematica -- something which replaces a given node on the expression graph, rather than recursing through the graph in order to search for something that matches a particular form.
– Lucas Myers
Nov 11 at 22:45
1
Sorry...I meantepathtoolsin the same folder.
– smichr
Nov 13 at 14:47
add a comment |
up vote
1
down vote
accepted
Automatic distribution of constants is a touchy subject. There is an option to disable it as follows:
from sympy.core.evaluate import distribute
with distribute(False):
poly1 = 6/(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or you can wrap 25 in UnevaluatedExpr to prevent its interaction with other terms.
poly1 = 6/(UnevaluatedExpr(25)*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6*25**(-1)/(x + 3) + 1/(5*(x + 3)**2)
Or use the un-evaluated product (Mul) in the denominator:
poly1 = 6/Mul(25, x+3, evaluate=False) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or wrap the denominator in factor_terms -- a gentler form of factor which does the job of extracting the coefficient without messing too much with the expression.
poly1 = 6/factor_terms(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or cheat by introducing a symbol that looks like a number:
c25 = symbols('25')
poly1 = 6/(c25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 1/(5*(x + 3)**2) + 6/(25*(x + 3))
Suggested reading: Prevent expression evaluation
The second question, about targeted replacement, is hard to answer in this generality. One has to recurse through the expression tree, rebuilding expr as expr.func(*args) where args are expr.args, possibly modified. The main issue is how you will know that this instance of 25*x + 75 is the one that should be replaced.
2
And that about covers it! Great summary of methods. As for the second question, take a look at the not-oft-mentioned traversaltools in simplify.
– smichr
Nov 11 at 18:50
@smichr, the documentation for traversaltools seems sparse, so just to clarify:use()applies some function to every argument at a given level on the expression tree? Is there a way to specify one particular node of the graph (i.e. one argument of the expression) to apply some function to? @Welcome to Stack Overflow, I'm looking for something like theReplacePartfunction from Mathematica -- something which replaces a given node on the expression graph, rather than recursing through the graph in order to search for something that matches a particular form.
– Lucas Myers
Nov 11 at 22:45
1
Sorry...I meantepathtoolsin the same folder.
– smichr
Nov 13 at 14:47
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
Automatic distribution of constants is a touchy subject. There is an option to disable it as follows:
from sympy.core.evaluate import distribute
with distribute(False):
poly1 = 6/(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or you can wrap 25 in UnevaluatedExpr to prevent its interaction with other terms.
poly1 = 6/(UnevaluatedExpr(25)*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6*25**(-1)/(x + 3) + 1/(5*(x + 3)**2)
Or use the un-evaluated product (Mul) in the denominator:
poly1 = 6/Mul(25, x+3, evaluate=False) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or wrap the denominator in factor_terms -- a gentler form of factor which does the job of extracting the coefficient without messing too much with the expression.
poly1 = 6/factor_terms(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or cheat by introducing a symbol that looks like a number:
c25 = symbols('25')
poly1 = 6/(c25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 1/(5*(x + 3)**2) + 6/(25*(x + 3))
Suggested reading: Prevent expression evaluation
The second question, about targeted replacement, is hard to answer in this generality. One has to recurse through the expression tree, rebuilding expr as expr.func(*args) where args are expr.args, possibly modified. The main issue is how you will know that this instance of 25*x + 75 is the one that should be replaced.
Automatic distribution of constants is a touchy subject. There is an option to disable it as follows:
from sympy.core.evaluate import distribute
with distribute(False):
poly1 = 6/(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or you can wrap 25 in UnevaluatedExpr to prevent its interaction with other terms.
poly1 = 6/(UnevaluatedExpr(25)*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6*25**(-1)/(x + 3) + 1/(5*(x + 3)**2)
Or use the un-evaluated product (Mul) in the denominator:
poly1 = 6/Mul(25, x+3, evaluate=False) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or wrap the denominator in factor_terms -- a gentler form of factor which does the job of extracting the coefficient without messing too much with the expression.
poly1 = 6/factor_terms(25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 6/(25*(x + 3)) + 1/(5*(x + 3)**2)
Or cheat by introducing a symbol that looks like a number:
c25 = symbols('25')
poly1 = 6/(c25*(x+3)) + 1/(5*(x + 3)**2)
print(poly1) # 1/(5*(x + 3)**2) + 6/(25*(x + 3))
Suggested reading: Prevent expression evaluation
The second question, about targeted replacement, is hard to answer in this generality. One has to recurse through the expression tree, rebuilding expr as expr.func(*args) where args are expr.args, possibly modified. The main issue is how you will know that this instance of 25*x + 75 is the one that should be replaced.
answered Nov 10 at 22:03
user6655984
2
And that about covers it! Great summary of methods. As for the second question, take a look at the not-oft-mentioned traversaltools in simplify.
– smichr
Nov 11 at 18:50
@smichr, the documentation for traversaltools seems sparse, so just to clarify:use()applies some function to every argument at a given level on the expression tree? Is there a way to specify one particular node of the graph (i.e. one argument of the expression) to apply some function to? @Welcome to Stack Overflow, I'm looking for something like theReplacePartfunction from Mathematica -- something which replaces a given node on the expression graph, rather than recursing through the graph in order to search for something that matches a particular form.
– Lucas Myers
Nov 11 at 22:45
1
Sorry...I meantepathtoolsin the same folder.
– smichr
Nov 13 at 14:47
add a comment |
2
And that about covers it! Great summary of methods. As for the second question, take a look at the not-oft-mentioned traversaltools in simplify.
– smichr
Nov 11 at 18:50
@smichr, the documentation for traversaltools seems sparse, so just to clarify:use()applies some function to every argument at a given level on the expression tree? Is there a way to specify one particular node of the graph (i.e. one argument of the expression) to apply some function to? @Welcome to Stack Overflow, I'm looking for something like theReplacePartfunction from Mathematica -- something which replaces a given node on the expression graph, rather than recursing through the graph in order to search for something that matches a particular form.
– Lucas Myers
Nov 11 at 22:45
1
Sorry...I meantepathtoolsin the same folder.
– smichr
Nov 13 at 14:47
2
2
And that about covers it! Great summary of methods. As for the second question, take a look at the not-oft-mentioned traversaltools in simplify.
– smichr
Nov 11 at 18:50
And that about covers it! Great summary of methods. As for the second question, take a look at the not-oft-mentioned traversaltools in simplify.
– smichr
Nov 11 at 18:50
@smichr, the documentation for traversaltools seems sparse, so just to clarify:
use()applies some function to every argument at a given level on the expression tree? Is there a way to specify one particular node of the graph (i.e. one argument of the expression) to apply some function to? @Welcome to Stack Overflow, I'm looking for something like the ReplacePart function from Mathematica -- something which replaces a given node on the expression graph, rather than recursing through the graph in order to search for something that matches a particular form.– Lucas Myers
Nov 11 at 22:45
@smichr, the documentation for traversaltools seems sparse, so just to clarify:
use()applies some function to every argument at a given level on the expression tree? Is there a way to specify one particular node of the graph (i.e. one argument of the expression) to apply some function to? @Welcome to Stack Overflow, I'm looking for something like the ReplacePart function from Mathematica -- something which replaces a given node on the expression graph, rather than recursing through the graph in order to search for something that matches a particular form.– Lucas Myers
Nov 11 at 22:45
1
1
Sorry...I meant
epathtools in the same folder.– smichr
Nov 13 at 14:47
Sorry...I meant
epathtools in the same folder.– smichr
Nov 13 at 14:47
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53243409%2freformat-pieces-of-expressions-in-sympy-to-prevent-distribution-of-constant-coef%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown