sympy / sympy

A computer algebra system written in pure Python
https://sympy.org/
Other
12.92k stars 4.42k forks source link

(all) GeometryEntity should return equation #12366

Open smichr opened 7 years ago

smichr commented 7 years ago

For Point(x1, y1), the equation could be (x - x1)*(y - y1) and for objects like Segment, a Piecewise could be returned. I'm not sure what could be returned for the undefined region, however. Maybe I?

siefkenj commented 7 years ago

The graph of solutions to (x - x1)*(y - y1)==0 looks like a + symbol. I'm not quite sure the utility of this. Things of co-dimension 1 are level curves of nice functions, and if the co-dimension is higher, you should use a system of equations.

Of course, you can get things of higher co-dimension if you allow your function to have a critical value there. For example Point(x1,y1) is the unique solution to (x-x1)**2+(y-y1)**2==0. You could also do terrible things if you allow Abs in your functions.

smichr commented 7 years ago

look like a + symbol

I knew that x**2 - a*x*y - y**2 looked like that but convinced myself that what I entered was right...but you are. I like the square form, however. The utility is that one could use a general solver for geometrical object intersections. Perhaps the individual solvers for 1D, 2D-limited (like Segment) and general equations is better.

siefkenj commented 7 years ago

You'd have to be careful though. The intersection of Point(0,0) and Line(Point(0,0),Point(1,1)) is Point(0,0), but x**2+y**2 == y - x has other solutions. You need x**2+y**2 == y - x == 0 to limit yourself to the correct solution. Or am I misinterpreting how you'd aim to use the solver?

smichr commented 7 years ago

Or am I misinterpreting how you'd aim to use the solver?

No, that's what I intend. What other solutions are you thinking of for the equation?

>>> solve((x**2+y**2,y-x))
[{x: 0, y: 0}]
siefkenj commented 7 years ago

x**2+y**2 == y-x has solutions (0,0) and (0,1) if we're restricted to the reals.

smichr commented 7 years ago

Leave a comment

has solutions (0,0) and (0,1) if we're restricted to the reals.

Yes, but we aren't looking for solutions found by setting the two equations equal; we want only solutions that satisfy both equations. Only (0, 0) does that.

siefkenj commented 7 years ago

Maybe I don't understand how solve works. solve((x**2+y**2,y-x)) finds points where both x**2+y**2==0 and y-x==0? If that is the case, then you're right. I though it somehow was solving for when x**2+y**2==y-x.

smichr commented 7 years ago

If that is the case

yes, that's how it works.

smichr commented 7 years ago

Perhaps the Piecewise could contain a NaN for the region outside of the range or domain of interest:

>>> solve(Piecewise((x+1,x>-2),(nan,True))+x/2)
[-2/3]

But it looks like there are some issues:

>>> solve((Piecewise((y**2-x+1,x>0),(nan,True)),y-x/2))
[]

But I was expecting

>>> solve((y**2-x+1,y-x/2))
[{x: 2, y: 1}]

which verifies as the solution with the Piecewise, so I'm not sure why it missed it.

>>> Piecewise((y**2-x+1,x>0),(nan,True)).subs(_[0])
0
smichr commented 7 years ago

For segments, the following could be returned:

>> Segment((0,0),(0,1)).equation(x,y)
'Piecewise((x, 0<=y<=1)}'
>> Segment((0,0),(1,0)).equation(x,y)
'Piecewise((y, 0<=x<=1)}'
>> Segment((0,0),(1,2)).equation(x,y)
'Piecewise((-2*x + y, 0<=x<=1)}'

using this method

def equation(self, x, y):
    p1, p2 = self.args
    u, v = x, y
    if self.slope is S.Infinity:
        a, b = p1.y, p2.y
    else:
        a, b=p1.x, p2.x
        u, v = v, u
    if a > b:
        a, b = b, a
    return 'Piecewise((%s, %s<=%s<=%s)}'%(Line(self).equation(x, y), a, v, b)