{"id":1789,"date":"2026-01-30T22:00:00","date_gmt":"2026-01-31T03:00:00","guid":{"rendered":"https:\/\/aristotle2digital.blogwyrm.com\/?p=1789"},"modified":"2026-01-08T09:39:44","modified_gmt":"2026-01-08T14:39:44","slug":"a-symbolic-experiment-part-2-factoring","status":"publish","type":"post","link":"https:\/\/aristotle2digital.blogwyrm.com\/?p=1789","title":{"rendered":"A Symbolic Experiment \u2013 Part 2: Factoring"},"content":{"rendered":"\n<p>Last month we started on a journey to explore and experiment with the computer algebra system SymPy that is freely available in the Python ecosystem.&nbsp; The aim is to create, within this package, a rule system that implements the basic transformations and identities of the Fourier Transform.&nbsp; But the goal is very loose and a great deal of emphasis is placed on the journey more so than the final product.&nbsp; To this end, there are three focus areas:&nbsp; 1) working out the steps needed to manipulate symbolic expressions, 2) looking at what an intelligent agent would need to do as a way of exploring more artificial intelligence, and 3) discovering how the human does these steps differently and, in the process, having some new found appreciation for the subtleties and brilliance of the human mind.<\/p>\n\n\n\n<p>To start, we look at a classic algebraic manipulation that comes up often in the study of all sorts of disciplines ranging from computer graphics, to gravity and electromagnetism, to geometry and trigonometry \u2013 namely the application of the Pythagorean theorem to find the distance or magnitude of a vector by computing the square root of the sum of the squares.<\/p>\n\n\n\n<p>To keep things notationally simple, we\u2019ll consider the very simple expression:<\/p>\n\n\n\n<p>\\[ D = \\sqrt{ (x-a)^2 + y^2 } \\; \\]<\/p>\n\n\n\n<p>made up of the symbols $\\{a,x,y\\}$.<\/p>\n\n\n\n<p>In a variety of settings, society \u2018expects\u2019 that competent students of algebra to either recognize or, at a minimum, be able to verify that<\/p>\n\n\n\n<p>\\[ D\u2019 = \\sqrt{ x^2 \u2013 2 a x + a^2 + y^2} \\; \\]<\/p>\n\n\n\n<p>is \u2018equal\u2019 to $D$.&nbsp;<\/p>\n\n\n\n<p>Of course, the word \u2018equal\u2019 very elastic and, as a result, it isn\u2019t precise enough for either deep exploration of the human mind or for the shallow, do-as-I-am-told workings for a computer.&nbsp; Let\u2019s try to nail that down with some better definitions.<\/p>\n\n\n\n<p>First, let\u2019s define the term <em>mathematically equal<\/em> to contain the meaning that a teacher wants to convey when he says that $D=D\u2019$.&nbsp; Mathematical equality means that for every choice of values for $\\{a,x,y\\}$ the numerical result obtained by substitution from $D$ is exactly the same as the numerical result obtained from $D\u2019$ by the same process.<\/p>\n\n\n\n<p>Now let\u2019s define the term <em>structurally equal<\/em> to mean that the formal way the symbols are written in the expression are the same even if the identity of the symbols are not.&nbsp; For example,<\/p>\n\n\n\n<p>\\[ D\u2019\u2019 = \\sqrt{ (q-q_0)^2 + p^2 } \\; \\]<\/p>\n\n\n\n<p>is structurally equal to the expression for $D$ since we recognize that the symbol substitutions<\/p>\n\n\n\n<p>\\[ x \\rightarrow q \\; ,\\]<\/p>\n\n\n\n<p>\\[ a \\rightarrow q_0 \\; , \\]<\/p>\n\n\n\n<p>and<\/p>\n\n\n\n<p>\\[ y \\rightarrow p \\; \\]<\/p>\n\n\n\n<p>make $D$ look the same on paper as $D\u2019\u2019$.&nbsp; Note that two expressions that are structurally equal need not be mathematically equal if assumptions about the different symbols aren\u2019t the same.&nbsp; For example, if $x \\in (-\\infty,\\infty)$ but we restrict $p \\in [0,\\infty]$, then, despite their structurally equality $D$ is not mathematically equal to $D\u2019\u2019$ when $x &lt; 0$.<\/p>\n\n\n\n<p>We will use the term <em>exactly equal<\/em> to mean that two expressions are both mathematical equal and structurally equal and have the same symbols.<\/p>\n\n\n\n<p>These three definitions have holes and limitations.&nbsp; The holes are a by-product of limitations of human logic and we won\u2019t try to patch them so much as work around them when the time comes.&nbsp; Regarding the limitations, we can give a general notion of where they will show up and then revisit them in the future.&nbsp; The primary limitation(s) is that the notion of equivalency is left out.&nbsp; To give a flavor of this consider the two expressions<\/p>\n\n\n\n<p>\\[ \\frac{d}{dx} \\left( x^2 &#8211; 3 a x + 9 \\right) \\; \\]<\/p>\n\n\n\n<p>and<\/p>\n\n\n\n<p>\\[ &nbsp;2x -3a \\; .\\]<\/p>\n\n\n\n<p>These two expressions are neither mathematically equal (one can\u2019t simply substitute in a value for $x$ before taking the derivative) nor structurally equal (the symbol structure isn\u2019t the same).&nbsp; But they are equivalent in the sense that applying the derivative in the first leads one to the second.&nbsp; And, there is another wrinkle when considering moving from the second expression to the first, in that $2x &#8211; 3a$ is equivalent to an infinite number of expressions of the form<\/p>\n\n\n\n<p>\\[ \\frac{d}{dx} \\left( x^2 &#8211; 3 a x + constant \\right) \\; .\\]<\/p>\n\n\n\n<p>Since we will have our hand full just dealing with how to teach an agent how to determine if $D$ is structurally or mathematically equal to $D\u2019$, we will defer these deeper matters and look at a simple example from basic physics.<\/p>\n\n\n\n<p>It is typical for a professor, when teaching say electromagnetism, to look at $D\u2019$ and simply highlight the first three terms under the radical and say something to the effect that the form a perfect square which can be \u2018reduced\u2019 or \u2018simplified\u2019 to the other.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_simplification.png\"><img loading=\"lazy\" decoding=\"async\" width=\"857\" height=\"467\" src=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_simplification.png\" alt=\"\" class=\"wp-image-1785\" style=\"width:462px;height:auto\" srcset=\"https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_simplification.png 857w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_simplification-300x163.png 300w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_simplification-768x419.png 768w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_simplification-810x441.png 810w\" sizes=\"auto, (max-width: 857px) 100vw, 857px\" \/><\/a><\/figure><\/div>\n\n\n<p>However, there is no cognitive mind behind a computer (no matter how much training data it may have ingested) and so it can\u2019t fill in the gaps and move (albeit not usually effortlessly) between the various ambiguities and elastic meanings in the way a human can.&nbsp;<\/p>\n\n\n\n<p>To understand this point better, consider that to represent the expression above requires nesting $x^2 &#8211; 2 a x + a^2 + y^2$ under a square root symbol.&nbsp; That\u2019s four terms \u2018owned\u2019 by the square root, which we wish to \u2018factor\u2019 into two terms $(x-a)^2 + y^2$.&nbsp; In addition, each of these terms is complicated as none are \u2018atomic\u2019.&nbsp; A term is atomic if it consists of a symbol and nothing else.<\/p>\n\n\n\n<p>Driving this point home is easier done with a visual. Using the graphviz application and the corresponding Python API, we can visually display how these various expressions are represented internally.&nbsp; SymPy uses a tree structure that, for the expression $D\u2019$, looks like<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large\"><a href=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"454\" src=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree-1024x454.png\" alt=\"\" class=\"wp-image-1788\" srcset=\"https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree-1024x454.png 1024w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree-300x133.png 300w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree-768x341.png 768w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree-1536x681.png 1536w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree-810x359.png 810w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_1_tree.png 2000w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure><\/div>\n\n\n<p>Every node in the a SymPy tree is either a function or a symbol.&nbsp; Functions own (almost always) children nodes reflecting their composite.&nbsp; Symbols are terminal nodes reflecting their atomic nature.&nbsp; At the top of the tree is the Pow function (for power) with two main branches:&nbsp; Add and Half.&nbsp; Add is the function that owns the four terms that algebraically add together while Half is a special symbol meaning 1\/2.&nbsp; SymPy reserves a special symbol for this since division by 2 is so common. &nbsp;Of the four main branches of Add, three are Pow and one is Mul (for multiply).&nbsp; Like Add, Mul can own an arbitrary number of branches.&nbsp; In this case there are three, each terminating with the symbols $-2$, $a$, and $x$.&nbsp;&nbsp;<\/p>\n\n\n\n<p>In order to manipulate the only some of the contents under the square root we must be able to find that portion of the tree that corresponds to $x^2 \u2013 2 a x + a^2$, remove it, manipulate it, and then return the new structure to the tree so that it looks like:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_tree.png\"><img loading=\"lazy\" decoding=\"async\" width=\"605\" height=\"819\" src=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_tree.png\" alt=\"\" class=\"wp-image-1786\" srcset=\"https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_tree.png 605w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_sqrt_tree-222x300.png 222w\" sizes=\"auto, (max-width: 605px) 100vw, 605px\" \/><\/a><\/figure><\/div>\n\n\n<p>Getting the contents of the square root is relatively simple:&nbsp; we simple ask for the arguments of the expression and we get a tuple containing the Add branch and the Half Symbol.<\/p>\n\n\n\n<p>The Add branch is now a polynomial expression that we might be tempted to try SymPy\u2019s factor on.&nbsp; However, Factor doesn\u2019t know what to do with the portion involving $y^2$.&nbsp; However, if we isolate the portion of the expression involving just $x$ and $a$ by subtracting off the $y^2$ piece, factoring, and then adding $y^2$ back, we get a reasonable result.&nbsp; Both of these approaches are shone in the notebook snippet below:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><a href=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_Factor_Experiment.png\"><img loading=\"lazy\" decoding=\"async\" width=\"827\" height=\"857\" src=\"http:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_Factor_Experiment.png\" alt=\"\" class=\"wp-image-1787\" style=\"width:466px;height:auto\" srcset=\"https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_Factor_Experiment.png 827w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_Factor_Experiment-289x300.png 289w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_Factor_Experiment-768x796.png 768w, https:\/\/aristotle2digital.blogwyrm.com\/wp-content\/uploads\/2026\/01\/A2D_01Jan_2026_Factor_Experiment-810x839.png 810w\" sizes=\"auto, (max-width: 827px) 100vw, 827px\" \/><\/a><\/figure><\/div>\n\n\n<p>This behavior is not unique to either this situation nor to SymPy.&nbsp; Asking Wolfram Alpha to factor $x^2 -2 a x + a^2$ works fine but asking it to perform the same function on $x^2 -2ax + a^2 + y^2$ doesn\u2019t give an acceptable answer (although its answer differs from SymPy\u2019s default but coincides with SymPy being directed to factor of the field of the reals).<\/p>\n\n\n\n<p>Two final points.&nbsp; First, there is an algorithmic way of doing the separation of the polynomial into a $a$-$x$ part and a remainder that can be run without as much hand-holding as this snippet shows:<\/p>\n\n\n\n<div class=\"myQuoteDiv\">\n<pre class=\"wp-block-preformatted\">\na, x, y = sym.symbols(\u2018a x y')\n\npoly = x**2 - 2*a*x + a**2 + y**2\n\nax_part = sum(\n\u00a0 \u00a0 term for term in expr.as_ordered_terms()\n\u00a0 \u00a0 if term.has(a, x) and not term.has(y)\n)\n\nrest = poly - ax_part\n\nsym.factor(ax_part) + rest\n<\/pre>\n<\/div>\n\n\n\n<p>Second, and far more important.&nbsp; Just for fun, I asked Chat GPT to factor $x^2 -2 a x + a^2 + y^2$ both absent from and under the square root and it delivered the \u2018professorial\u2019 answer $(x-a)^2 + y^2$ in either case.&nbsp; It was also able to factor a more difficult SymPy example of $2x^5 + 2x^4y + 4x^3 + 4x^2y + 2x + 2y + a$ into $2(x+y)(x^2 + 1)^2 + a$ even though both Wolfram Alpha and Sympy could not out of the box.&nbsp; I suspect the reasons for these successes are either that these are well-known examples that reside somewhere within its system or it knows how to make these systems work better than I do.&nbsp; The next logical question is then why are SymPy and Mathematica not out of business.&nbsp; I think the only answer to this is that these success are superficial.&nbsp; That real mathematical creativity is still beyond the capabilities of the machine.&nbsp; But, I suppose, time will tell.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last month we started on a journey to explore and experiment with the computer algebra system SymPy that is freely available in the Python ecosystem.&nbsp; The aim is to create,&#8230; <a class=\"read-more-button\" href=\"https:\/\/aristotle2digital.blogwyrm.com\/?p=1789\">Read more &gt;<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1789","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=\/wp\/v2\/posts\/1789","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1789"}],"version-history":[{"count":7,"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=\/wp\/v2\/posts\/1789\/revisions"}],"predecessor-version":[{"id":1796,"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=\/wp\/v2\/posts\/1789\/revisions\/1796"}],"wp:attachment":[{"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1789"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1789"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/aristotle2digital.blogwyrm.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1789"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}