- Notifications
You must be signed in to change notification settings - Fork 46.7k
/
Copy pathsimultaneous_linear_equation_solver.py
142 lines (133 loc) · 5.16 KB
/
simultaneous_linear_equation_solver.py
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
"""
https://en.wikipedia.org/wiki/Augmented_matrix
This algorithm solves simultaneous linear equations of the form
λa + λb + λc + λd + ... = y as [λ, λ, λ, λ, ..., y]
Where λ & y are individual coefficients, the no. of equations = no. of coefficients - 1
Note in order to work there must exist 1 equation where all instances of λ and y != 0
"""
defsimplify(current_set: list[list]) ->list[list]:
"""
>>> simplify([[1, 2, 3], [4, 5, 6]])
[[1.0, 2.0, 3.0], [0.0, 0.75, 1.5]]
>>> simplify([[5, 2, 5], [5, 1, 10]])
[[1.0, 0.4, 1.0], [0.0, 0.2, -1.0]]
"""
# Divide each row by magnitude of first term --> creates 'unit' matrix
duplicate_set=current_set.copy()
forrow_index, rowinenumerate(duplicate_set):
magnitude=row[0]
forcolumn_index, columninenumerate(row):
ifmagnitude==0:
current_set[row_index][column_index] =column
continue
current_set[row_index][column_index] =column/magnitude
# Subtract to cancel term
first_row=current_set[0]
final_set= [first_row]
current_set=current_set[1::]
forrowincurrent_set:
temp_row= []
# If first term is 0, it is already in form we want, so we preserve it
ifrow[0] ==0:
final_set.append(row)
continue
forcolumn_indexinrange(len(row)):
temp_row.append(first_row[column_index] -row[column_index])
final_set.append(temp_row)
# Create next recursion iteration set
iflen(final_set[0]) !=3:
current_first_row=final_set[0]
current_first_column= []
next_iteration= []
forrowinfinal_set[1::]:
current_first_column.append(row[0])
next_iteration.append(row[1::])
resultant=simplify(next_iteration)
foriinrange(len(resultant)):
resultant[i].insert(0, current_first_column[i])
resultant.insert(0, current_first_row)
final_set=resultant
returnfinal_set
defsolve_simultaneous(equations: list[list]) ->list:
"""
>>> solve_simultaneous([[1, 2, 3],[4, 5, 6]])
[-1.0, 2.0]
>>> solve_simultaneous([[0, -3, 1, 7],[3, 2, -1, 11],[5, 1, -2, 12]])
[6.4, 1.2, 10.6]
>>> solve_simultaneous([])
Traceback (most recent call last):
...
IndexError: solve_simultaneous() requires n lists of length n+1
>>> solve_simultaneous([[1, 2, 3],[1, 2]])
Traceback (most recent call last):
...
IndexError: solve_simultaneous() requires n lists of length n+1
>>> solve_simultaneous([[1, 2, 3],["a", 7, 8]])
Traceback (most recent call last):
...
ValueError: solve_simultaneous() requires lists of integers
>>> solve_simultaneous([[0, 2, 3],[4, 0, 6]])
Traceback (most recent call last):
...
ValueError: solve_simultaneous() requires at least 1 full equation
"""
iflen(equations) ==0:
raiseIndexError("solve_simultaneous() requires n lists of length n+1")
_length=len(equations) +1
ifany(len(item) !=_lengthforiteminequations):
raiseIndexError("solve_simultaneous() requires n lists of length n+1")
forrowinequations:
ifany(notisinstance(column, (int, float)) forcolumninrow):
raiseValueError("solve_simultaneous() requires lists of integers")
iflen(equations) ==1:
return [equations[0][-1] /equations[0][0]]
data_set=equations.copy()
ifany(0inrowforrowindata_set):
temp_data=data_set.copy()
full_row= []
forrow_index, rowinenumerate(temp_data):
if0notinrow:
full_row=data_set.pop(row_index)
break
ifnotfull_row:
raiseValueError("solve_simultaneous() requires at least 1 full equation")
data_set.insert(0, full_row)
useable_form=data_set.copy()
simplified=simplify(useable_form)
simplified=simplified[::-1]
solutions: list= []
forrowinsimplified:
current_solution=row[-1]
ifnotsolutions:
ifrow[-2] ==0:
solutions.append(0)
continue
solutions.append(current_solution/row[-2])
continue
temp_row=row.copy()[: len(row) -1 :]
whiletemp_row[0] ==0:
temp_row.pop(0)
iflen(temp_row) ==0:
solutions.append(0)
continue
temp_row=temp_row[1::]
temp_row=temp_row[::-1]
forcolumn_index, columninenumerate(temp_row):
current_solution-=column*solutions[column_index]
solutions.append(current_solution)
final= []
foriteminsolutions:
final.append(float(round(item, 5)))
returnfinal[::-1]
if__name__=="__main__":
importdoctest
doctest.testmod()
eq= [
[2, 1, 1, 1, 1, 4],
[1, 2, 1, 1, 1, 5],
[1, 1, 2, 1, 1, 6],
[1, 1, 1, 2, 1, 7],
[1, 1, 1, 1, 2, 8],
]
print(solve_simultaneous(eq))
print(solve_simultaneous([[4, 2]]))