# Is AlgebraicRulesData magical?

I am trying to understand what AlgebraicRules is all about in the answer to this question. It apparently returns an AlgebraicRulesData with the following usage:

AlgebraicRulesData is an object returned by AlgebraicRules. Its OutputForm appears to be a list of rules, but the rules will be used algebraically rather than syntactically by Replace and related functions.

That's weird! Observe:

ex = AlgebraicRules[
{x^2 + 2y - 4 == 6, x^2 + y^2 == 0}, {x, y}]

AlgebraicRulesData[{SolveSolvVar[x],SolveSolvVar[y]},{x,y},
-10+SolveSolvVar[x]^2+2 SolveSolvVar[y]==0&&SolveSolvVar[x]^2+SolveSolvVar[y]^2==0,
{{{0,{{2,1},{1,-2},{0,10}}}},{{2,{{0,1}}},{0,{{1,2},{0,-10}}}}},
{x,y},{y^2->-10+2 y,x^2->10-2 y},Rational]


Apparently, I can use ReplaceAll (/.) with this, and I don't get a ReplaceAll::reps error!

x^2 /. ex

(*  10 - 2*y  *)


Even weirder is that if I copy the entire output and try to literally replace with it, it doesn't work! I get an AlgebraicRules::algdat error.

x^2 /. AlgebraicRulesData[{SolveSolvVar[x],SolveSolvVar[y]},{x,y},
-10+SolveSolvVar[x]^2+2 SolveSolvVar[y]==0&&SolveSolvVar[x]^2+SolveSolvVar[y]^2==0,
{{{0,{{2,1},{1,-2},{0,10}}}},{{2,{{0,1}}},{0,{{1,2},{0,-10}}}}},
{x,y},{y^2->-10+2 y,x^2->10-2 y},Rational]

(* x^2 *)


Would someone explain to me what is happening that allows ex to be used as a replacement rule, but not the literal expression?

• You've run into the fact that Mathematica isn't actually an immutable perfectly homoiconic language (BTW I'm pretty sure there is no such language since they all need some kind of mutable internal representation). In essence, there's a constructed AlgebraicRulesData that the C++ side of the kernel knows how to work with, but which can't be constructed by just calling AlgebraicRulesData on its data. It's good to keep in mind that everything we work with in Mathematica is really a C++ object. Helps you write better code. – b3m2a1 Jan 20 at 6:46
• Think about this: {AssociationQ@<|1 -> 2|>, AssociationQ@Unevaluated[<|1 -> 2|>], Head@Unevaluated[<|1 -> 2|>]} The data itself is the same, and yet AssociationQ says that one is True and one is not. You can also set special bits with, e.g. SystemPrivateHoldSetNoEntry that won't be copied if you copy-paste the expression, but which will be held if you keep them bound to a variable or otherwise preserve the identity of the expression (e.g. by just passing it through your code). There are good number of places where this is used productively on this site. – b3m2a1 Jan 20 at 6:57
• (1) What AlgebraicRulesData really is, is obsolete.Yes, it is still supported. Or ignored, to be more accurate. As for the copy/paste business, it has an internal validation flag. Those do not survive copying and in the case of AlgebraicRulesData there is no way (or attempt) to revalidate them. Without the flag being set, rule replacement will not handle them. – Daniel Lichtblau Jan 20 at 15:18
• (2) The comments by @b3m2a1 are quite on the mark, especially in giving an indication of how validation flags might be used. – Daniel Lichtblau Jan 20 at 15:19
• Very interesting! Thanks for the explanations. Either @b3m2a1 or DanielLichtblau should write this as an answer so I can accept it. – QuantumDot Jan 20 at 17:49

• @QuantumDot Could try using SystemPrivate context functions such as SetValid but I will note that this can have unforeseen consequences. – Daniel Lichtblau Oct 1 at 19:24
• Thank you. It seems SystemPrivateValidQ yields True for expressions that were not previously declared with SystemPrivateSetValid. For example SystemPrivateValidQ[x+1] yields True. Have I miss understood it? Thank you again! – QuantumDot Oct 1 at 21:45