8
$\begingroup$

Is there a way to reliably test the equality of two plots? Consider this:

plot1 = Plot[Sin[x], {x, 0, 2Pi}];
plot2 = Plot[Sin[x], {x, 0, 2Pi}];

You'd think these would be equal, but they're not.

Evaluate[plot1 == plot2]

Mathematica graphics

SameQ doesn't work either:

Evaluate[plot1 === plot2]
(* False *)

At least this works:

Evaluate[plot1 == plot1]
(* True *)

Edit:

@eyorble provided a nice answer, but the plot thickens. How can we also get False when two plots are not equal?

plot3 = Plot[Cos[x], {x, 0, 2Pi}];
(plot1 == plot3) /. (x_String :> StringReplace[x, "Charting`Private`Tag$" ~~ __ -> "Charting`Private`Tag"])

Mathematica graphics

$\endgroup$
3
  • $\begingroup$ The newer versions add some sort of unique tag each time Plot is executed. Makes comparison pretty much impossible $\endgroup$
    – Michael E2
    Commented Feb 11, 2018 at 23:25
  • $\begingroup$ Any thoughts on a workaround? $\endgroup$
    – Chris K
    Commented Feb 11, 2018 at 23:30
  • $\begingroup$ Removing the tag (or remapping it as in the answer) would work. $\endgroup$
    – Michael E2
    Commented Feb 12, 2018 at 3:09

3 Answers 3

7
$\begingroup$
plot1 == plot2 /. 
  (x_String :> StringReplace[x, "Charting`Private`Tag$" ~~ __ -> "Charting`Private`Tag"])

True

Plots seem to be otherwise deterministic, so that appears to be the only necessary change for comparison with ==.

To get False when they aren't equal, perhaps something like this would suffice:

Activate[Inactive[SameQ][plot1, plot2]
   /. (x_String :> StringReplace[x, "Charting`Private`Tag$" ~~ __ -> "Charting`Private`Tag"])]

Inactive and Activate are simply to ensure that SameQ doesn't evaluate before the replacement takes place.

$\endgroup$
3
  • $\begingroup$ Thanks! I realized another important case is to get False when two plots are not equal. See my edit to the question. Any ideas there? $\endgroup$
    – Chris K
    Commented Feb 12, 2018 at 2:39
  • $\begingroup$ @ChrisK Updated my answer for that. $\endgroup$
    – eyorble
    Commented Feb 12, 2018 at 2:46
  • $\begingroup$ Seems to work. Thanks again! $\endgroup$
    – Chris K
    Commented Feb 12, 2018 at 2:57
7
$\begingroup$

As I observed earlier, the tags are used in plots in the form Annotation[curve, tag] for each function plotted. One way to just get the curves is to override Annotation:

Block[{Annotation = #1 &},
 plot1 == plot2
 ]
(*  True  *)

Block[{Annotation = #1 &},
 plot1 === plot2
 ]
(*  True  *)

Since the tags are in the Charting`Private` context, it seems pointless to have them in the first place. (Even if they are used in constructing the plot, what good are they in the final output, ostensibly private and hidden from the user?)

Note on Equal vs. SameQ: Equal will evaluate to True when expressions are the same (as in SameQ), but it tends to remain unevaluated if there are symbols (which might take on arbitrary values). To be sure to get a False, use SameQ:

Plus == Automatic
(*  Plus == Automatic  *)

Plus === Automatic
(*  False  *)

See 1 is not the SameQ as Null, but why might 1 be Equal to Null?

Also related: (4390), (8796), (17909).

$\endgroup$
1
  • $\begingroup$ I have a Hash@expr based caching procedure for my APIFunctions and now I need to patch it because of that -.- I'd call it a minor bug. $\endgroup$
    – Kuba
    Commented Mar 8, 2018 at 22:32
3
$\begingroup$

If by equal you mean the plots look the same and are the same size then you can use Rasterize and ImageData.

samePlot[p1_, p2_] := Equal @@ (ImageData@Rasterize[#, "Image"] & /@ {p1, p2})

With

plot1 = Plot[Sin[x], {x, 0, 2 Pi}];
plot2 = Plot[Sin[x], {x, 0, 2 Pi}];
plot3 = Plot[Cos[x], {x, 0, 2 Pi}];

Then

samePlot[plot1, plot2]
True
samePlot[plot1, plot3]
False

Hope this helps.

$\endgroup$
1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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