Can I simplify an expression into form which uses my own definitions?

57

34

This seems like a simple thing to do, but I couldn't find anything relevant from Mathematica documentation.

So suppose I have an expression:

a*b/(a + a*Cos[a/b])

And I have defined:

k=a/b

Now I want to simplify the expression above so that the simplify would use my definition of k in place of a/b in as many places as possible so that the final expression would look something like:

a/(k+k*Cos[k])

This was just a simple example I made up to demonstrate what I'd like to do, but I have encountered a similar situations many times every now and then.

Echows

Posted 2012-04-02T08:56:22.443

Reputation: 941

Answers

46

Daniel Lichtblau and Andrzej Koslowski posted a solution in mathgroup, which I adjusted marginally. (I like to use german identifiers, because they will never clash with Mma builtins). That's the code:

SetAttributes[termErsetzung,Listable];
termErsetzung[expr_, rep_, vars_] := 
Module[{num = Numerator[expr], den = Denominator[expr],
        hed = Head[expr], base, expon},
  If[PolynomialQ[num, vars] && PolynomialQ[den, vars] && ! NumberQ[den], 
    termErsetzung[num, rep, vars]/termErsetzung[den, rep, vars], (*else*)
    If[hed === Power && Length[expr] === 2,        
       base  = termErsetzung[expr[[1]], rep, vars];
       expon = termErsetzung[expr[[2]], rep, vars];
       PolynomialReduce[base^expon, rep, vars][[2]],        (*else*)
      If[Head[Evaluate[hed]] === Symbol && 
        MemberQ[Attributes[Evaluate[hed]], NumericFunction], 
        Map[termErsetzung[#, rep, vars] &, expr],    (*else*)
       PolynomialReduce[expr, rep, vars][[2]] ]]]
];

TermErsetzung[rep_Equal,vars_][expr_]:=
  termErsetzung[expr,Evaluate[Subtract@@rep],vars]//Union;

Usage is like this:

a*b/(a + a*Cos[a/b]) // TermErsetzung[k b == a, b]

a/(k (1 + Cos[k]))

The first parameter is the "replacement equation", the second the variable (or list of variables) to be eliminated:

a*b/(a + a*Cos[a/b]) // TermErsetzung[k b == a, {a, b}] 

{b/(1 + Cos[k]), a/(k (1 + Cos[k]))}

Peter Breitfeld

Posted 2012-04-02T08:56:22.443

Reputation: 4 892

Thanks! This combined with FullSimplify seemed to do exactly what I wanted. – Echows – 2012-04-02T09:34:44.097

7If you want to prevent name conflicts with built-in names the canonic method is to start your variable names with a lowercase letter. German names are no guarantee, they may still conflict with built-in ones (EigenSystem and GröbnerBasis are examples) and are less convenient for the majority of people here that do not speak German. – Sjoerd C. de Vries – 2012-04-02T15:16:53.197

@Sjoerd in "normal" circumstances I always start with lower case letter, but for functions in my "helper-functions-package" I like Capitalize. – Peter Breitfeld – 2012-04-02T15:21:57.937

18

Mr.Wizard

Posted 2012-04-02T08:56:22.443

Reputation: 259 163

wow! An "answer" linking to other answers on the same question? You definitely are taking this to new heights :O – rm -rf – 2013-12-25T17:36:03.603

@rm-rf New heights? The post is from two years ago. ;-p This information needs to be somewhere; do you have a better idea? – Mr.Wizard – 2013-12-25T17:37:50.140

1Yes, I know that (see deleted comments) :) My only suggestion before was to not merge them, but I see that's now useless as well :P The merge made a link self-referential, hence my comment. In any case, I try to tell folks not to post "link only" answers so I don't see why this answer should be treated differently. (Or should we start posting answers with only cross-links to other answers on related questions as well?) But I don't really care... the weather today is just too magnificent to not go outside! – rm -rf – 2013-12-25T17:48:56.033

@rm-rf Sorry, I didn't remember the full history of this. I needed to refer to this answer and I found you had deleted the question it was attached to some time ago (which I don't disagree with). Since the question was already deleted I didn't (and don't) see the harm in merging, so I popped my answer over here with a merge. Regarding link-only answers I think occasionally they are OK, especially if the links are numerous and all to SE resources that wont go dead. Nevertheless it was for that concern that I merged an old answer rather than posting a new one. – Mr.Wizard – 2013-12-25T18:20:38.787

@rm-rf And I ran out of character space, but *Merry Christmas!* – Mr.Wizard – 2013-12-25T18:21:01.943

Merry Christmas to you too! :) – rm -rf – 2013-12-25T18:36:47.710

11

In this simple example you can just use a rule. In more complex cases it might not be straighforward to generalize.

Simplify[a*b/(a + a*Cos[a/b]) /. a -> k b]

(* b/(1 + Cos[k]) *)

b.gates.you.know.what

Posted 2012-04-02T08:56:22.443

Reputation: 18 845

8

Rephrasing your question, what you want is to eliminate a given variable by introducing another one. There are two ways to go about it:

  • The first (and easiest) is simply to express you change in variable in a rule, such as b -> a/k, and use it in a call to ReplaceAll (aka /.). This gives the following code:

    In[1]:= a*b/(a + a*Cos[a/b]) /. b -> a/k
    Out[1]= a^2/(k (a + a Cos[k]))
    
  • The second way, it is covered in this Mathematica tutorial. You can use Eliminate to that aim, but it might not do exactly what you intend. For example, in your example, it will actually go further than you intended:

    In[4]:= Eliminate[{U == a*b/(a + a*Cos[a/b]) && k == a/b}, a]
    Out[4]= (-ArcCos[(b - U)/U] == k && b != 0) || (ArcCos[(b - U)/U] == k && b != 0)
    

F'x

Posted 2012-04-02T08:56:22.443

Reputation: 10 517

Actually you could follow that with U /. First@Solve[%, U, Reals]. I don't know if there are situations where that would be preferred to b.gatessucks's answer. – A.G. – 2013-12-23T02:15:32.493