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.










share|improve this question




























    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.










    share|improve this question


























      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.










      share|improve this question















      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






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 10 at 23:44







      user6655984

















      asked Nov 10 at 21:07









      Lucas Myers

      236




      236
























          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.






          share|improve this answer

















          • 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 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




            Sorry...I meant epathtools in the same folder.
            – smichr
            Nov 13 at 14:47











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          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

























          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.






          share|improve this answer

















          • 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 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




            Sorry...I meant epathtools in the same folder.
            – smichr
            Nov 13 at 14:47















          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.






          share|improve this answer

















          • 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 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




            Sorry...I meant epathtools in the same folder.
            – smichr
            Nov 13 at 14:47













          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.






          share|improve this answer












          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.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          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 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




            Sorry...I meant epathtools in the same folder.
            – smichr
            Nov 13 at 14:47














          • 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 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




            Sorry...I meant epathtools in 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


















          draft saved

          draft discarded




















































          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.




          draft saved


          draft discarded














          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





















































          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







          Popular posts from this blog

          How to pass form data using jquery Ajax to insert data in database?

          National Museum of Racing and Hall of Fame

          Guess what letter conforming each word