On Wed, 19 May 2021 at 07:41, Martin Teichmann <martin.teichmann@gmail.com> wrote:

Hi list,

To frame the problem, let us try to solve the equation x ** 2 == 1/2 using sympy:

>>> from sympy import Eq, solve, symbols, S

>>> x = symbols("x")

>>> solve(Eq(x**2, S(1)/2))

[-sqrt(2)/2, sqrt(2)/2]

that worked well, but actually we would like to write the last line simply as

>>> solve(x**2 == 1/2)

as you might notice, this is fully legal Python syntax. Unfortunately the semantics is such that sympy has no way to determine what is actually going on, this is why they invented all those helper functions shown above.

Numpy override __eq__ liberally to allow this kind of behaviour (though not root searching, but returning ndarray instead of a boolean for == so things remain matrices. As a toy example to show that it is definitely possible to let the x "poison the well":

```

class Symbolic:

def __init__(self, expression):

self.expression = expression

def __pow__(self, power):

return Symbolic(f"{self.expression} ** {power}")

def __eq__(self, other):

return Symbolic(f"{self.expression} == {other}")

def __truediv__(self, other):

return Symbolic(f"{self.expression} / {other}")

def __str__(self):

return self.expression

def __repr__(self):

return f"{self.__class__}({self.expression})"

x = Symbolic("x")

print(x ** 2 == 1 / 2)

print(x ** 2 == Symbolic(1) / 2)

def __init__(self, expression):

self.expression = expression

def __pow__(self, power):

return Symbolic(f"{self.expression} ** {power}")

def __eq__(self, other):

return Symbolic(f"{self.expression} == {other}")

def __truediv__(self, other):

return Symbolic(f"{self.expression} / {other}")

def __str__(self):

return self.expression

def __repr__(self):

return f"{self.__class__}({self.expression})"

x = Symbolic("x")

print(x ** 2 == 1 / 2)

print(x ** 2 == Symbolic(1) / 2)

```

Which gives output:

```

x ** 2 == 0.5

x ** 2 == 1 / 2

x ** 2 == 1 / 2

```

Now, it hasn't done root solving, but it could (or return an object that could), so to say that "Unfortunately the semantics is such that sympy has no way to determine what is actually going on" is an unsound foundation for your idea.

My idea is now to start at the line above, "x = symbols('x')". I propose a new syntax, "symbolic x", which tells the parser that x is a symbolic variable, and expressions should not be executed, but handed over as such to the calling functions.

So... what you're suggesting can basically already be done, though as I did above, might require some additional "poisoning" so that all roots are poisoned, just like when there was the thread about float literals (e.g. 1F / 3 to become Float(1, 3)).