Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

python algorithm for solving systems of equations without

Writer Matthew Barrera

I need algorithm, that solve systems like this:

Example 1:

5x - 6y = 0 <--- line
(10- x)**2 + (10- y)**2 = 2 <--- circle 

Solution:

find y:
(10- 6/5*y)**2 + (10- y)**2 = 2
100 - 24y + 1.44y**2 + 100 - 20y + y**2 = 2
2.44y**2 - 44y + 198 = 0
D = b**2 - 4ac
D = 44*44 - 4*2.44*198 = 3.52
y[1,2] = (-b+-sqrt(D))/2a
y[1,2] = (44+-1.8761)/4.88 = 9.4008 , 8.6319
find x:
(10- x)**2 + (10- 5/6y)**2 = 2
100 - 20x + y**2 + 100 - 5/6*20y + (5/6*y)**2 = 2
1.6944x**2 - 36.6666x + 198 = 0
D = b**2 - 4ac
D = 36.6666*36.6666 - 4*1.6944*198 = 2.4747
x[1,2] = (-b+-sqrt(D))/2a
x[1,2] = (36.6666+-1.5731)/3.3888 = 11.2841 , 10.3557

my skills are not enough to write this algorithm please help

and another algorithm that solve this system.

5x - 6y = 0 <--- line
|-10 - x| + |-10 - y| = 2 <--- rhomb

as answer here i need two x and two y.

3

1 Answer

You can use sympy, Python's symbolic math library.

Solutions for fixed parameters

from sympy import symbols, Eq, solve
x, y = symbols('x y', real=True)
eq1 = Eq(5 * x - 6 * y, 0)
eq2 = Eq((10 - x) ** 2 + (10 - y) ** 2, 2)
solutions = solve([eq1, eq2], (x, y))
print(solutions)
for x, y in solutions: print(f'{x.evalf()}, {y.evalf()}')

This leads to two solutions:

[(660/61 - 6*sqrt(22)/61, 550/61 - 5*sqrt(22)/61), (6*sqrt(22)/61 + 660/61, 5*sqrt(22)/61 + 550/61)]
10.3583197613288, 8.63193313444070
11.2810245009662, 9.40085375080520

The other equations work very similar:

eq1 = Eq(5 * x - 6 * y, 0)
eq2 = Eq(Abs(-10 - x) + Abs(-10 - y), 2)

leading to :

[(-12, -10), (-108/11, -90/11)]
-12.0000000000000, -10.0000000000000
-9.81818181818182, -8.18181818181818

Dealing with arbitrary parameters

For your new question, how to deal with arbitrary parameters, sympy can help to find formulas, at least when the structure of the equations is fixed:

from sympy import symbols, Eq, Abs, solve
x, y = symbols('x y', real=True)
a, b, xc, yc = symbols('a b xc yc', real=True)
r = symbols('r', real=True, positive=True)
eq1 = Eq(a * x - b * y, 0)
eq2 = Eq((xc - x) ** 2 + (yc - y) ** 2, r ** 2)
solutions = solve([eq1, eq2], (x, y))

Studying the generated solutions, some complicated expressions are repeated. Those could be substituted by auxiliary variables. Note that this step isn't necessary, but helps a lot in making sense of the solutions. Also note that substitution in sympy often only considers quite literal replacements. That's by the introduction of c below is done in two steps:

c, d = symbols('c d', real=True)
for xi, yi in solutions: print(xi.subs(a ** 2 + b ** 2, c) .subs(r ** 2 * a ** 2 + r ** 2 * b ** 2, c * r ** 2) .subs(-a ** 2 * xc ** 2 + 2 * a * b * xc * yc - b ** 2 * yc ** 2 + c * r ** 2, d) .simplify()) print(yi.subs(a ** 2 + b ** 2, c) .subs(r ** 2 * a ** 2 + r ** 2 * b ** 2, c * r ** 2) .subs(-a ** 2 * xc ** 2 + 2 * a * b * xc * yc - b ** 2 * yc ** 2 + c * r ** 2, d) .simplify())

Which gives the formulas:

x1 = b*(a*yc + b*xc - sqrt(d))/c
y1 = a*(a*yc + b*xc - sqrt(d))/c
x2 = b*(a*yc + b*xc + sqrt(d))/c
y2 = a*(a*yc + b*xc + sqrt(d))/c

These formulas then can be converted to regular Python code without the need of sympy. That code will only work for an arbitrary line and circle. Some tests need to be added around, such as c == 0 (meaning the line is just a dot), and d either be zero, positive or negative.

The stand-alone code could look like:

import math
def give_solutions(a, b, xc, yc, r): # intersection between a line a*x-b*y==0 and a circle with center (xc, yc) and radius r c =a ** 2 + b ** 2 if c == 0: print("degenerate line equation given") else: d = -a**2 * xc**2 + 2*a*b * xc*yc - b**2 * yc**2 + c * r**2 if d < 0: print("no solutions") elif d == 0: print("1 solution:") print(f" x1 = {b*(a*yc + b*xc)/c}") print(f" y1 = {a*(a*yc + b*xc)/c}") else: # d > 0 print("2 solutions:") sqrt_d = math.sqrt(d) print(f" x1 = {b*(a*yc + b*xc - sqrt_d)/c}") print(f" y1 = {a*(a*yc + b*xc - sqrt_d)/c}") print(f" x2 = {b*(a*yc + b*xc + sqrt_d)/c}") print(f" y2 = {a*(a*yc + b*xc + sqrt_d)/c}")

For the rhombus, sympy doesn't seem to be able to work well with abs in the equations. However, you could use equations for the 4 sides, and test whether the obtained intersections are inside the range of the rhombus. (The four sides would be obtained by replacing abs with either + or -, giving four combinations.)

Working this out further, is far beyond the reach of a typical stackoverflow answer, especially as you seem to ask for an even more general solution.

2

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy