147
$\begingroup$

Is it possible in Mathematica to get a step-by-step evaluation of some functions; that's to say, outputting not only the result but all the stages that have led to it? If so, how does one do it?

Example : Let's say I want to know the steps to get the derivative of $\cos x\times\exp x$; it should first tell me that it's equal to $\frac{d}{dx}(\exp x)\times\cos x+\exp x \times \frac{d}{dx}(\cos x)$ and then render the result to say $\exp{x}\times(\cos x-\sin x)$.

$\endgroup$
5
  • 2
    $\begingroup$ This comes up regularly on MathGroup and the answer is usually somewhat negative (though some commercial packages exist). I think (not sure) version 5 had a (very limited) package for this though. $\endgroup$
    – Szabolcs
    Commented Jan 18, 2012 at 12:12
  • 7
    $\begingroup$ In this instance, could do WolframAlpha["derivative of exp(x)*cos(x)"] then hit "Show steps" at upper right. $\endgroup$ Commented Jan 18, 2012 at 16:36
  • 1
    $\begingroup$ What about 'Trace'? It's not as good looking as the solutions below but is built in and always works. $\endgroup$
    – Lior Blech
    Commented May 5, 2016 at 21:15
  • $\begingroup$ I am surprised no one gave the simple answer, by simply adding "=" before your command. So in this example, =D[Cos[x]*Exp[x],x] should send you straight to WolframAlpha to get your step by step solution. This require internet connection though. $\endgroup$
    – IAmNoOne
    Commented May 1, 2022 at 5:07
  • $\begingroup$ out of topic, but you can try derivative-calculator.net and integral-calculator.com , which is useful even for non-mathematica user. $\endgroup$ Commented Jul 15, 2023 at 14:17

7 Answers 7

121
$\begingroup$

For differentiation at least, old versions of Mathematica had a demonstration function called WalkD[] that holds your hand and shows what is done at each stage up until the final answer.

In general, however...

You should realize at the outset that while knowing about the internals of Mathematica may be of intellectual interest, it is usually much less important in practice than you might at first suppose.

Indeed, one of the main points of Mathematica is that it provides an environment where you can perform mathematical and other operations without having to think in detail about how these operations are actually carried out inside your computer.

...

Particularly in more advanced applications of Mathematica, it may sometimes seem worthwhile to try to analyze internal algorithms in order to predict which way of doing a given computation will be the most efficient. And there are indeed occasionally major improvements that you will be able to make in specific computations as a result of such analyses.

But most often the analyses will not be worthwhile. For the internals of Mathematica are quite complicated, and even given a basic description of the algorithm used for a particular purpose, it is usually extremely difficult to reach a reliable conclusion about how the detailed implementation of this algorithm will actually behave in particular circumstances.

A typical problem is that Mathematica has many internal optimizations, and the efficiency of a computation can be greatly affected by whether the details of the computation do or do not allow a given internal optimization to be used.

Put another way: how Mathematica does things doesn't necessarily correspond to "manual" methods.


Here's my modest attempt to (somewhat) modernize WalkD[]:

Format[d[f_, x_], TraditionalForm] := DisplayForm[RowBox[{FractionBox["\[DifferentialD]",
                                                  RowBox[{"\[DifferentialD]", x}]], f}]];

SpecificRules = {d[(f_)[u___, x_, v___], x_] /;
                 FreeQ[{u}, x] && FreeQ[{v}, x] :> D[f[u, x, v], x],
                 d[(a_)^(x_), x_] :> D[a^x, x] /; FreeQ[a, x]};

ConstantRule = d[c_, x_] :> 0 /; FreeQ[c, x];

LinearityRule = {d[f_ + g_, x_] :> d[f, x] + d[g, x],
                 d[c_ f_, x_] :> c d[f, x] /; FreeQ[c, x]};

PowerRule = {d[x_, x_] :> 1, d[(x_)^(a_), x_] :> a*x^(a - 1) /; FreeQ[a, x]};

ProductRule = d[f_ g_, x_] :> d[f, x] g + f d[g, x];

QuotientRule = d[(f_)/(g_), x_] :> (d[f, x]*g - f*d[g, x])/g^2;

InverseFunctionRule = d[InverseFunction[f_][x_], x_] :>
                      1/f'[InverseFunction[f][x]];

ChainRule = {d[(f_)^(a_), x_] :> a*f^(a - 1)*d[f, x] /; FreeQ[a, x],
             d[(a_)^(f_), x_] :> Log[a]*a^f*d[f, x] /; FreeQ[a, x],
             d[(f_)[g__], x_] /; ! FreeQ[{g}, x] :>
             (Derivative[##][f][g] & @@@ IdentityMatrix[Length[{g}]]).(d[#, x] & /@ {g}),
             d[(f_)^(g_), x_] :> f^g*d[g*Log[f], x]};

$RuleNames = {"Specific Rules", "Constant Rule", "Linearity Rule", "Power Rule",
              "Product Rule", "Quotient Rule", "Inverse Function Rule", "Chain Rule"};

displayStart[expr_] := CellPrint[
  Cell[BoxData[MakeBoxes[HoldForm[expr], TraditionalForm]], "Output", 
   Evaluatable -> False, CellMargins -> {{Inherited, Inherited}, {10, 10}}, 
   CellFrame -> False, CellEditDuplicate -> False]]

displayDerivative[expr_, k_Integer] := CellPrint[
  Cell[BoxData[TooltipBox[RowBox[{InterpretationBox["=", Sequence[]], "  ", 
       MakeBoxes[HoldForm[expr], TraditionalForm]}], $RuleNames[[k]], 
     LabelStyle -> "TextStyling"]], "Output", Evaluatable -> False, 
   CellMargins -> {{Inherited, Inherited}, {10, 10}}, 
   CellFrame -> False, CellEditDuplicate -> False]]

WalkD[f_, x_] := Module[{derivative, oldderivative, k}, 
        derivative = d[f, x]; displayStart[derivative];
        While[! FreeQ[derivative, d],
            oldderivative = derivative; k = 0;
            While[oldderivative == derivative,
                      k++;
                      derivative = derivative /. 
                              ToExpression[StringReplace[$RuleNames[[k]], " " -> ""]]];
            displayDerivative[derivative, k]];
        D[f, x]]

I've tried to make the formatting of the derivative look a bit more traditional, as well as having the differentiation rule used be a tooltip instead of an explicitly generated cell (thus combining the best features of WalkD[] and RunD[]); you'll only see the name of the differentiation rule used if you mouseover the corresponding expression.

WalkD[] demonstration

$\endgroup$
8
  • 2
    $\begingroup$ I hoped it was possible but the answer seems no. I'm accepting the answer in a few days if nobody finds another solution. Thank you ! $\endgroup$
    – Cydonia7
    Commented Jan 18, 2012 at 12:17
  • 1
    $\begingroup$ You should put quotient rule before product rule or it will never be used. $\endgroup$
    – Tyilo
    Commented Aug 28, 2014 at 5:56
  • 1
    $\begingroup$ I just noticed that WalkD[Integrate[f[x],{x,g[x],h[x]}],x] results in an infinite loop of error outputs, each time adding an extra /. $Failed to the end. $\endgroup$
    – celtschk
    Commented Sep 5, 2014 at 17:12
  • $\begingroup$ @Tylio, as it turns out, quotients are already taken care of by the power rule and product rule... :D $\endgroup$ Commented May 2, 2015 at 3:52
  • $\begingroup$ @J.M., It is great, but it exists a little problem. If try WalkD[x^2+x+1,x], the return result does not contain needed "parentheses". $\endgroup$
    – tanghe2014
    Commented Jan 9, 2017 at 10:17
52
$\begingroup$

Use:

http://www.wolframalpha.com/input/?i=D[Cos[x]*Exp[x]%2C+x]

and select "Show steps". More in Mathematica would be

WolframAlpha["D[Cos[x]*Exp[x], x]"]

or even

WolframAlpha["D[Cos[x]*Exp[x], x]", IncludePods -> "Input", 
 AppearanceElements -> {"Pods"}, PodStates -> {"Input__Show steps"}]
$\endgroup$
7
  • 1
    $\begingroup$ I know this but my question is about Mathematica not Wolfram Alpha. I'm looking for something to see the steps of functions in Mathematica using either a feature or another function. $\endgroup$
    – Cydonia7
    Commented Jan 18, 2012 at 12:06
  • 2
    $\begingroup$ Note that within the current version of Mathematica, you can directly query Wolfram|Alpha (putting an "=" at the beginning of the Input cell, and then clicking the "Show Steps" button on the result returned). But I don't think we have any way of knowing whether the steps shown in the Wolfram|Alpha output are what goes on when you directly let the Mathematica kernel evaluate the derivative. $\endgroup$
    – murray
    Commented Jan 18, 2012 at 16:21
  • 7
    $\begingroup$ @murray, most likely the steps shown is not what is going on in Mathematica. $\endgroup$
    – user21
    Commented Jan 18, 2012 at 16:34
  • $\begingroup$ To @Skydreamer: yes, I said so in my comment! And what WolframAlpha shows is likely to be even more different from how Mathematica normally does it in the case of symbolic integration. $\endgroup$
    – murray
    Commented Jan 18, 2012 at 22:50
  • $\begingroup$ This answer is nice, but present day it is 'PodStates -> {"Input__Step-by-step solution"}`!!! $\endgroup$ Commented Mar 22, 2020 at 17:04
35
$\begingroup$

To see the steps for taking indefinite integrals one can use free rule-based integrator nicknamed Rubi crafted by Albert D. Rich:

Click on the sample integration problem at the end of the notebook and press Shift-Enter to evaluate it. After a minute or so depending on the speed of your computer, the first step of the integration should be displayed. To see successive steps, click on the intermediate results and press Shift-Enter.

In many cases this integrator produces terser output than the built-in.

$\endgroup$
3
  • 5
    $\begingroup$ Oh my. What have we here... +1 $\endgroup$
    – Mr.Wizard
    Commented Sep 24, 2013 at 9:30
  • 2
    $\begingroup$ That's an interesting integrator, but sometimes its rules are too general to be used as a step-by-step solution provider. E.g. I wanted to see a step-by-step integration of Sin[x] Exp[-x/a] WRT x, and all I got was the complete antiderivative via rule 4144, not a step a human would take like e.g. integration by parts, which W|A suggests in this case. $\endgroup$
    – Ruslan
    Commented May 29, 2015 at 15:48
  • 1
    $\begingroup$ bomb-diggity +1 $\endgroup$ Commented Sep 10, 2017 at 20:35
31
$\begingroup$

here is a function based on WolframAlpha[]

ShowSteps[exp_] := 
  WolframAlpha[ ToString@HoldForm@InputForm@exp, 
  {{"Input", 2}, "Content"},  PodStates -> {"Input__Show steps"}]

SetAttributes[ShowSteps, HoldAllComplete]

for limits use

PodStates -> {"Limit__Show steps"}

for integration

PodStates -> {"IndefiniteIntegral__Show steps"} 

Update:

WolframAlpha changed output.

Now ShowSteps should work with:

ShowSteps[exp_] := 
  WolframAlpha[ToString@HoldForm@InputForm@exp, 
  {{"Input", 1}, "Content"}, 
   PodStates -> {"Input__Step-by-step solution","Input__Show all steps"}]

 SetAttributes[ShowSteps, HoldAll]

enter image description here

Update - Nov 2014

ShowSteps[exp_] := 
 WolframAlpha[ToString@HoldForm@InputForm@exp, 
 {{"Input", 2}, "Content"}, 
 PodStates -> {"Input__Step-by-step solution"}]

SetAttributes[ShowSteps, HoldAll]
$\endgroup$
1
  • 3
    $\begingroup$ This looks great, but it seems like the proper form has changed. Can you tell us how you figured out the proper PodStates input, so we can update it in the future? $\endgroup$
    – Piquan
    Commented Oct 17, 2016 at 2:38
18
$\begingroup$

I have improved J. M.'s version of walkD by adding error handling. I have also added walkInt that works like walkD except for integration. Code:

Format[d[f_, x_], TraditionalForm] := Module[{paren, boxes},
    paren = MatchQ[f,Plus[_,__]];
    boxes = RowBox[{f}];
    If[paren,
        boxes = RowBox[{"(", boxes, ")"}]
    ];
    boxes = RowBox[{FractionBox["\[DifferentialD]", RowBox[{"\[DifferentialD]", x}]], boxes}];
    DisplayForm[boxes]
];

dSpecificRules = {d[x_, x_] :> 1, d[(f_)[x_], x_] :> D[f[x], x],
                 d[(a_)^(x_), x_] :> D[a^x, x] /; FreeQ[a, x]};

dConstantRule = d[c_, x_] :> 0 /; FreeQ[c, x];

dLinearityRule = {d[f_ + g_, x_] :> d[f, x] + d[g, x],
                 d[c_ f_, x_] :> c d[f, x] /; FreeQ[c, x]};

dPowerRule = {d[x_, x_] :> 1, d[(x_)^(a_), x_] :> a*x^(a - 1) /; FreeQ[a, x]};

dProductRule = d[f_ g_, x_] :> d[f, x] g + f d[g, x];

dQuotientRule = d[(f_)/(g_), x_] :> (d[f, x]*g - f*d[g, x])/g^2;

dInverseFunctionRule := d[InverseFunction[f_][x_], x_] :>
                      1/Derivative[1][f][InverseFunction[f][x]];

dChainRule = {d[(f_)^(a_), x_] :> a*f^(a - 1)*d[f, x] /; FreeQ[a, x],
             d[(a_)^(f_), x_] :> Log[a]*a^f*d[f, x] /; FreeQ[a, x],
             d[(f_)[g_], x_] :> (D[f[x], x] /. x -> g)*d[g, x],
             d[(f_)^(g_), x_] :> f^g*d[g*Log[f], x]};

$dRuleNames = {"Specific Rules", "Constant Rule", "Linearity Rule", "Power Rule",
              "Quotient Rule", "Product Rule", "Inverse Function Rule", "Chain Rule"};

displayStart[expr_] := CellPrint[
    Cell[BoxData[MakeBoxes[HoldForm[expr], TraditionalForm]], "Output", 
        Evaluatable -> False, CellMargins -> {{Inherited, Inherited}, {10, 10}}, 
        CellFrame -> False, CellEditDuplicate -> False]];

displayDerivative[expr_, k_Integer] := CellPrint[
    Cell[BoxData[TooltipBox[RowBox[{InterpretationBox["=", Sequence[]], "  ", 
        MakeBoxes[HoldForm[expr], TraditionalForm]}], "Differentation: " <> $dRuleNames[[k]], 
        LabelStyle -> "TextStyling"]], "Output", Evaluatable -> False, 
    CellMargins -> {{Inherited, Inherited}, {10, 10}}, 
    CellFrame -> False, CellEditDuplicate -> False]];

walkD::differentationError = "Failed to differentiate expression!";

walkD[f_, x_] := Module[{derivative, oldderivative, k}, 
    derivative = d[f, x]; displayStart[derivative];
    While[! FreeQ[derivative, d],
        oldderivative = derivative; k = 0;
        While[oldderivative == derivative,
            k++;
            If[k > Length@$dRuleNames,
				Message[walkD::differentationError];
				Return[D[f, x]];
			];
			derivative = derivative /. ToExpression["d" <> StringReplace[$dRuleNames[[k]], " " -> ""]]
        ];
        displayDerivative[derivative, k]];
    D[f, x]
];


Format[int[f_,x_],TraditionalForm]:= (
    paren = MatchQ[f,Plus[_,__]];
    boxes = RowBox[{f}];
    If[paren,
        boxes = RowBox[{"(", boxes, ")"}]
    ];
    boxes = RowBox[{boxes, "\[DifferentialD]", x}];
    boxes = RowBox[{"\[Integral]", boxes}];
    DisplayForm[boxes]
);

intSpecificRules = {int[(f_)[x_], x_] :> Integrate[f[x], x],
                   int[(a_)^(x_), x_] :> Integrate[a^x, x] /; FreeQ[a, x]};

intConstantRule = int[c_, x_] :> c*x /; FreeQ[c, x];

intLinearityRule = {int[f_ + g_, x_] :> int[f, x] + int[g, x],
                   int[c_ f_, x_] :> c int[f, x] /; FreeQ[c, x]};

intPowerRule = {int[x_, x_] :> x^2 / 2, int[1/x_, x_] :> Log[x], int[(x_)^(a_), x_] :> x^(a + 1)/(a + 1) /; FreeQ[a, x]};

intSubstitutionRule = {
                        int[(f_)^(a_), x_] :> ((Integrate[u^a, u] / d[f, x]) /. u -> f) /; FreeQ[a, x] && FreeQ[D[f, x], x],
                        int[(f_)^(a_) g_, x_] :> ((Integrate[u^a, u] / d[f, x]) * g /. u -> f) /; FreeQ[a, x] && FreeQ[FullSimplify[D[f, x] / g], x],
                        int[(a_)^(f_), x_] :> (a ^ f)/(d[f, x] * Log[a]) /; FreeQ[a, x] && FreeQ[D[f, x], x],
                        int[(a_)^(f_) g_, x_] :> (a ^ f)/(d[f, x] * Log[a]) * g /; FreeQ[a, x] && FreeQ[FullSimplify[D[f, x] / g], x],
                        int[(f_)[g_], x_] :> (Integrate[f[u], u] /. u -> g) / d[g, x] /; FreeQ[D[g, x], x],
                        int[(f_)[g_] h_, x_] :> (Integrate[f[u], u] /. u -> g) / d[g, x] * h /; FreeQ[FullSimplify[D[g, x] / h], x]
                    };

intProductRule = int[f_ g_, x_] :> int[f, x] g - int[int[f, x] * d[g, x], x];

$intRuleNames = {"Specific Rules", "Constant Rule", "Linearity Rule", "Power Rule", "Substitution Rule", "Product Rule"};

displayIntegral[expr_, k_Integer] := CellPrint[
  Cell[BoxData[TooltipBox[RowBox[{InterpretationBox["=", Sequence[]], "  ", 
       MakeBoxes[HoldForm[expr], TraditionalForm]}], "Integration: " <> $intRuleNames[[k]], 
     LabelStyle -> "TextStyling"]], "Output", Evaluatable -> False, 
   CellMargins -> {{Inherited, Inherited}, {10, 10}}, 
   CellFrame -> False, CellEditDuplicate -> False]];

walkInt::integrationError = "Failed to integrate expression!";
walkInt::differentationError = "Failed to differentiate expression!";

walkInt[f_, x_] := Module[{integral, oldintegral, k, leafcounts, ruleused},
    integral = int[f, x]; displayStart[integral];
    leafcounts = {};
    ruleused = "";
    While[! FreeQ[integral, int],
        If[ruleused == "Product Rule",
            AppendTo[leafcounts, LeafCount @ integral];
            If[Length @ leafcounts >= 5 && OrderedQ @ Take[leafcounts, -5],
                Message[walkInt::integrationError];
                Return[Integrate[f, x]];
            ];
        ];
        oldintegral = integral; k = 0;
        While[oldintegral == integral,
            k++;
            If[k > Length@$intRuleNames,
				Message[walkInt::integrationError];
				Return[Integrate[f, x]];
			];
			integral = integral /. ToExpression["int" <> StringReplace[$intRuleNames[[k]], " " -> ""]]
        ];
        ruleused = $intRuleNames[[k]];
		displayIntegral[integral, k];
		While[! FreeQ[integral, d],
			oldintegral = integral; k = 0;
			While[oldintegral == integral,
				k++;
				If[k > Length@$dRuleNames,
                    Message[walkInt::differentationError];
                    Return[Integrate[f, x]];
                ];
                integral = integral /. ToExpression["d" <> StringReplace[$dRuleNames[[k]], " " -> ""]]
            ];
            displayDerivative[integral, k]];
        ];
    Integrate[f, x]
];

Sample output:

enter image description here

$\endgroup$
5
  • $\begingroup$ the walkD has problem when evaluate the following: walkInt[x^2/(1 + x^4), x], and will be trapped into dead loop $\endgroup$ Commented Aug 13, 2014 at 6:52
  • 1
    $\begingroup$ @LCFactorization it should fail now instead. $\endgroup$
    – Tyilo
    Commented Aug 23, 2014 at 18:31
  • 1
    $\begingroup$ thank you for the update! Two suggestions for reference: (1)I still got error message for the problem I mentioned: walkInt::integrationError: Failed to integrate expression!; can this be removed? (2)Is it possible to use simplify in some of the intermediate steps? $\endgroup$ Commented Aug 24, 2014 at 1:57
  • $\begingroup$ PS: ` LabelStyle -> "TextStyling"` option may not be valid in all MMA versions. $\endgroup$ Commented Aug 24, 2014 at 1:59
  • 1
    $\begingroup$ @LCFactorization (1) I'm a noob at math, so I just implemented a few integration rules and walkInt doesn't know how to evaluate that integral. The error is there to show that walkInt couldn't get to the result one step at a time and it just gets Mathematica to integrate it. (2) Certainly although I'm not sure if this could have any adverse effects. $\endgroup$
    – Tyilo
    Commented Aug 24, 2014 at 2:46
4
$\begingroup$

I found this answer from Quora by Vitaliy Kaurov: https://www.quora.com/Can-Mathematica-show-me-step-by-step-solutions

Wolfram|Alpha (W|A) is integrated in Wolfram Language (WL or Mathematica) via function WolframAlpha that can place API calls to W|A servers. So you can pull step-by-step solutions into your notebook via simple WL code like:

WolframAlpha[
  "integrate 1/(1+cos(x)^2)", 
  {{"IndefiniteIntegral", 2}, "Content"}, 
  PodStates -> {"IndefiniteIntegral__Step-by-step solution"}]

This works well for me.

$\endgroup$
2
  • $\begingroup$ Does this consume cloud credits? $\endgroup$ Commented Apr 28, 2019 at 21:36
  • 2
    $\begingroup$ It doesn't consume cloud credits. @Chunde, I appreciate that you are trying to help but please note that this information is already in FDSg's answer and user21's answer. $\endgroup$
    – C. E.
    Commented Apr 28, 2019 at 22:01
-2
$\begingroup$

The output of

WolframAlpha["D[Cos[x]*Exp[x], x]", IncludePods -> "Input", 
 AppearanceElements -> {"Pods"}, PodStates -> {"Input__Show steps"}]

is

enter image description here

$\endgroup$
1

Not the answer you're looking for? Browse other questions tagged or ask your own question.