21
$\begingroup$

Already at least in version 2 (I think), the function Solve calls the function Roots. At that time, I had a rather dirty trick, that still works, to verify this:

Unprotect[Roots];
Roots[x___] /; (Print[HoldForm[Roots[x]]];False) := Null;
Protect[Roots];
Solve[x^3 - 2 x + 12 ==0, x];

(* Roots[12-2 x+x^3==0,x,Cubics->True,Quartics->True] *)

Unprotect[Roots]; Clear[Roots]; Protect[Roots];

Later, this fact could be found much easier by using the function Trace with option TraceInternal->True. Since Trace wraps the expressions in HoldForm, the following worked much better:

Cases[Trace[Solve[x^3 - 2 x + 12 ==0, x], Roots, TraceInternal->True], HoldForm[_Roots], Infinity]

It seems that I have not used the function Trace for a long time, for I just found that this command does not longer work in version 10, nor in version 9. The option TraceInternal of Trace is not listed any more, though when we ask for the options of Trace, it turns up.

Is there a successor of this option, or is there a more elegant way nowadays to see that internally Solve calls Roots?

I also observed that the syntax colouring (version 10, windows 7) suggests that Trace can be used with only two arguments. All further arguments are shown in red, even if they are black when used as a second argument. Is that correct?

$\endgroup$
  • $\begingroup$ TraceInternal -> True still works, although it is not documented and the syntax coloring suggests it is an error. But perhaps the way it works or the way Solve works has changed. $\endgroup$ – Michael E2 Dec 4 '14 at 16:45
  • $\begingroup$ @Michael Yes, I observed that as well. With the option TraceInternal->True the extra output shows something that seems to have to do with with numerical testing of an equality, but nothing of calling Roots, as it did before. And Solve still calls Roots, as you can see in the first output in my question. $\endgroup$ – Fred Simons Dec 4 '14 at 17:27
  • 2
    $\begingroup$ Sorry, somehow I forgot you mentioned Options[Trace] in the question. I had used the following to check the dependence on Roots: Block[{Roots = x == 1 &}, Solve[x^3 - 2 x + 12 == 0, x]]. The syntax coloring is determined by SyntaxInformation[Trace]. I do not know why it does not correspond to allowed usage. As to your main question, it might take someone from WRI to answer. $\endgroup$ – Michael E2 Dec 4 '14 at 19:19
  • $\begingroup$ Spelunk reveals nothing about Solve. $\endgroup$ – Michael E2 Dec 4 '14 at 19:21
  • $\begingroup$ @Michael No reason for sorry, instead thanks for your interest. Your way of testing if Roots is called is certainly much better and much more elegant than what I did more than 20 years ago. It can even give almost the same result: Block[{Roots = (Print[Inactive[Roots][##]]; x == 1) &}, Solve[x^3 - 2 x + 12 == 0, x]]. Once again thanks! $\endgroup$ – Fred Simons Dec 4 '14 at 19:48
19
$\begingroup$

Normally I like to use On and Off for this kind of tracing as it is easy to set up without modifying any symbols. However, it does not immediately work in this case:

On[Roots]
Solve[x^3 - 2 x + 12 == 0, x];
Off[]

This does not produce any trace messages. Something must be using Quiet to suppress them. We can check this hypothesis:

On[Quiet]
Solve[x^3 - 2 x + 12 == 0, x];
Off[]

trace message screenshot

Yes, indeed, some subcomponent within Solve is invoking Quiet. And it is not a targeted call: it is indiscriminately quieting all messages. No problem, let's just block Quiet while we are tracing Roots:

On[Roots]
Block[{Quiet}, Solve[x^3 - 2 x + 12 == 0, x]];
Off[]

trace message screenshot

That worked, revealing our Roots traces. But well, well, what else have we here? We also seem to have uncovered a bug wherein numerous invalid calls to SetStreamPosition are made. The indiscriminate use of Quiet certainly reduces the probability of this bug being found. There is a lesson here :)

This analysis was performed using Mathematica 10.0.1 on Windows 7, 64-bit.

UPDATE

I could not resist investigating the SetStreamPosition messages further. It turns out that they are being generated as the front-end is trying to link the buttons beside the trace messages to their corresponding documentation entries. Perhaps some documentation-related index file is out of date. The presence or absence of Quiet has no bearing on whether these messages appear. The bug is unmasked only because some trace messages have been generated.

$\endgroup$
  • $\begingroup$ This completely answers my question. Though the option TraceInternal->True for Trace still exists, it produces a different output now, and what I am looking for can better be done with On/Off in combination with switching off Quiet. Very nice, many thanks. I did not know that On/Off could be used for tracing; I only knew it for switching messages on/off. $\endgroup$ – Fred Simons Dec 6 '14 at 10:33
19
$\begingroup$

Let me first answer your second question, since I can only guess about the main question:

I also observed that the syntax colouring (version 10, windows 7) suggests that Trace can be used with only two arguments.

It's really just the coloring that goes wrong and has nothing to do with functionality. You can see that it is not even related to TraceInternal by using a officially documented option

Mathematica graphics

The reason for the wrong coloring is the FunctionInformation.m file. There, the coloring patterns for each built in function can be found and the one of Trace is just wrong

file = 
  ToFileName[{$InstallationDirectory, "SystemFiles", "Kernel", 
    "TextResources", CurrentValue["Language"]}, 
   "FunctionInformation.m"];
Cases[Import[file], {"Trace", __}, Infinity]
(* {{"Trace", {_, _.}}} *)

As you see, Trace is supposed to have 1 or optionally 2 arguments which is not correct. Fix it with the following and everything looks non-red:

Unprotect[Trace];
SyntaxInformation[Trace] = {"ArgumentsPattern" -> {_, _., OptionsPattern[]}};
Protect[Trace];

In the case of the behavior of TraceInternal one should first note, that it indeed still works. You can test this by e.g. search this site for TraceInternal and try the examples you find. You will see that it indeed traces internal functions, just not Roots.

What I suspect is that Wolfram turned tracing for some part of the Solve code off. I can kind of mimic something like this by using Block to temporarily overwrite the value of $TraceOn or $TraceOff. With this, I can prevent that the tracer steps into some part of my code. It seems Wolfram did something else because I couldn't find traces of something like that when looking closer at your Solve call. By looking closer I mean something like the following which prints the evaluation stack when Roots is reached.

Unprotect[Roots];
Roots[x___] := Block[{$insideRoots = True},
    Print[Stack[__]];
    Roots[x]
    ] /; Not[TrueQ[$insideRoots]];
Protect[Roots];

Solve[x^3 - 2 x + 12 == 0, x]

In the above output, you will find many things that are called, for instance PolynomialGCD.. Still it is not possible to catch those expressions with trace.

In my opinion the more general question should be: How is it possible to make parts of the evaluation completely invisible to trace?

$\endgroup$
  • $\begingroup$ Many thanks for your interesting answer. I learned a lot from it, in particular the very elegant way for printing the stack when Roots is called, without disturbing the execution of the Solve-command. I did indeed observe that calling Trace with the option TraceInternal->True produces output, now and then an impressive amount. But I seem to remember is that in the early versions of Mathematica this output was much more restricted. $\endgroup$ – Fred Simons Dec 6 '14 at 10:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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