Welcome, guest | Sign In | My Account | Store | Cart

A function to solve simultaneous equations in two variables.

>>> solve('3*x + 5*y = 29; 12*x - 3*y = 24')
(3.0, 4.0)
Python, 58 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
def solve(eq, var=('x', 'y')):
    """ Solve a system of simultaneous equation in
    two variables of the form

    2*x + 5*y=c1; 3*x - 5*y=c2

    Example: solve('12*x - 3*y = 21; 9*x  - 18*y=0')

    Should work for negative constants as well.

    Example: solve('3*x - 5*y=-11; 12*x + 3*y=48')

    Returns a two tuple of (x, y) values.

    NOTE: Won't denegarate to the special case
    of solving for only one variable.
    
    """

    var_re = re.compile(r'(\+|\-)\s*(\d*)\s*\*?\s*(x|y)')
    const_re = re.compile(r'(\+|\-)\s*(\-?\d+)$')

    constants, eqns, coeffs, default  = [],[], {'x': [], 'y': []}, {'': '1'}

    for e in eq.split(';'):
        eq1 = e.replace("="," - ").strip()
        if not eq1.startswith('-'):
            eq1 = '+' + eq1
        eqns.append(eq1)

    var_eq1, var_eq2 = map(var_re.findall, eqns)

    constants = [-1*int(x[0][1]) for x in map(const_re.findall, eqns)]
    [coeffs[x[2]].append(int((x[0]+ default.get(x[1], x[1])).strip())) for x in (var_eq1 + var_eq2)]
    
    ycoeff = coeffs['y']
    xcoeff = coeffs['x']

    # Adjust equations to take out y and solve for x
    if ycoeff[0]*ycoeff[1] > 0:
        ycoeff[1] *= -1
        xcoeff[0] *= ycoeff[1]
        constants[0] *= -1*ycoeff[1]        
    else:
        xcoeff[0] *= -1*ycoeff[1]
        constants[0] *= ycoeff[1]
        
    xcoeff[1] *= ycoeff[0]
    constants[1] *= -1*ycoeff[0]

    # Obtain x
    xval = sum(constants)*1.0/sum(xcoeff)

    # Now solve for y using value of x
    z = eval(eqns[0],{'x': xval, 'y': 1j})
    yval = -z.real*1.0/z.imag

    return (xval, yval)

This can be considered as an extension of an existing recipe "Linear equations solver" http://code.activestate.com/recipes/365013 . I wanted to see if one could extend it to write a solver in two variables. First it gets the y variable out of the way, solves for x and then uses x's value to solve for y in a way similar to recipe #365013.

The code could be much more cleaner and elegant than this I suppose.

2 comments

Andy Barbour 12 years, 3 months ago  # | flag

why reinvent the wheel?

>>> import numpy as np
>>> a = np.array([[3,5],[12,-3]]) 
>>> b = np.array([[29],[24]])
>>> np.linalg.solve(a,b)
array([[ 3.],
       [ 4.]])
Anand B Pillai (author) 12 years, 3 months ago  # | flag

The wheel has to be inherited from another vehicle.