I was given an outline of this code from my teacher, however I kept getting ModuleNotFoundError: No module named 'error'. I know that I need a module named error, however when I couldn't find a code for a module named error.
I am trying to solve this question:
Solve the tridiagonal equations Ax = b by Doolittle’s decomposition method, where:
A = [6 2 0 0 0
−1 7 2 0 0
0 −2 8 2 0
0 0 3 7 −2
0 0 0 3 5]
b = [2
−3
4
−3
1].
Here is the code that I was using:
from numpy import argmax, dot, zeros, array, asarray, tril, triu
def swapRows(v,i,j):
if len(v.shape) == 1: v[i],v[j] = v[j],v[i]
else:
temp = v[i].copy()
v[i] = v[j]
v[j] = temp
def swapCols(v,i,j):
temp = v[:,j].copy()
v[:,j] = v[:,i]
v[:,i] = temp
import error
def LUdecomp(a,tol=1.0e-9):
n = len(a)
seq = array(range(n))
# Set up scale factors
s = zeros(n)
for i in range(n):
s[i] = max(abs(a[i,:]))
for k in range(0,n-1):
# Row interchange, if needed
p = argmax(abs(a[k:n,k])/s[k:n]) + k
if abs(a[p,k]) < tol: error.err('Matrix is singular')
if p != k:
swapRows(s,k,p)
swapRows(a,k,p)
swapRows(seq,k,p)
# Elimination
for i in range(k+1,n):
if a[i,k] != 0.0:
lam = a[i,k]/a[k,k]
a[i,k+1:n] = a[i,k+1:n] - lam*a[k,k+1:n]
a[i,k] = lam
return a,seq
def LUsolve(a,b,seq):
n = len(a)
# Rearrange constant vector; store it in [x]
x = b.copy()
for i in range(n):
x[i] = b[seq[i]]
# Solution
for k in range(1,n):
x[k] = x[k] - dot(a[k,0:k],x[0:k])
x[n-1] = x[n-1]/a[n-1,n-1]
for k in range(n-2,-1,-1):
x[k] = (x[k] - dot(a[k,k+1:n],x[k+1:n]))/a[k,k]
return x
A = asarray( [ [ 6, 2, 0, 0, 0 ],
[ -1, 7, 2, 0, 0 ],
[ 0, -2, 8, 2, 0 ],
[ 0, 0, 3, 7, -2 ],
[ 0, 0, 0, 3, 5 ] ], dtype=float ) A_orig = A.copy() b = asarray( [ 2, -3, 4, -3, 1 ], dtype=float ) b_orig = b.copy()
A,seq = LUdecomp(A) # A is overwritten as L\U L = tril( A, -1 ) # extract L for ii in range(L.shape[0]): L[ii,ii] = 1.0 # add in 1's on the diagonal U = triu( A, 0 ) # extract U print ("L = ") print (L) print ("U = ") print (U) if False:
print ("A[seq,:]= ")
print (A_orig[seq,:])
print ("LU= ")
print (dot(L,U))
x = LUsolve(A,b,seq) print ("Solution= ", x)
If your intention is to throw an error at some point, then you can reach that without the import error statement. Raising an exception might be a solution.
See the documentation on errors and exceptions.
You can remove import error and edit
if abs(a[p,k]) < tol: error.err('Matrix is singular')
in LUdecomp() as follows:
if abs(a[p,k]) < tol:
raise Exception('Matrix is singular')
Related
Here's my python code for finding shortest path using djikstra's algorithm. The source is 0. I want to change the source to 1 and also for 2,3,4. What should I change to get that.
for eg, it is showing output as
0 to 0 is 0
0 to 1 is 4
0 to 2 is 12
0 to 3 is 11
0 to 4 is 19
i want output like
1 to 0 is
1 to 1 is
1 to 2 is
1 to 3 is
1 to 4 is
import sys
class Graph():
def __init__(self, vertices):
self.V = vertices
self.graph = [[0 for column in range(vertices)]
for row in range(vertices)]
def printSolution(self, dist):
print("Vertex \tDistance from Source")
for node in range(self.V):
print(node, "\t", dist[node])
def minDistance(self, dist, sptSet):
min = sys.maxsize
for u in range(self.V):
if dist[u] < min and sptSet[u] == False:
min = dist[u]
min_index = u
return min_index
def dijkstra(self, src):
dist = [sys.maxsize] * self.V
dist[src] = 0
sptSet = [False] * self.V
for cout in range(self.V):
x = self.minDistance(dist, sptSet)
sptSet[x] = True
for y in range(self.V):
if self.graph[x][y] > 0 and sptSet[y] == False and \
dist[y] > dist[x] + self.graph[x][y]:
dist[y] = dist[x] + self.graph[x][y]
self.printSolution(dist)
if __name__ == "__main__":
g = Graph(5)
g.graph = [
[0, 4, 0, 5, 0],
[4, 0, 8, 0, 0],
[0, 8, 0, 6, 7],
[0, 0, 6, 0, 9],
[0, 0, 7, 9, 0],
]
g.dijkstra(0)
Try changing the source while calling g.dijkstra() method.
This will allow the algorithm to know from where to start from.
g.dijkstra(1)
I am attempting to make a Lagrange interpolation function however after construction I get the error index 9 is out of bounds for axis 0 with size 9. Why am a receiving this error and how can I fix it to perform my interpolation?
import numpy as np
b = np.arange(3,12)
y = np.arange(9)
from sympy import Symbol
t = Symbol('t')
d = len(b)
def interpolation(x, z):
if len(x) != len(z):
print("Error: the length of x and z is different")
else:
L = 0
for i in range (d+1):
p = 1
for j in range (d+1):
if j != i:
p *= (t-x[j]/(x[i] - x[j]))
L += z[i]*p
print(interpolation(b, y))
Because the first index is a zero you can only go to the index 8 and 9 is then out of bounds. Your 9 indices are 0, 1, 2, 3, 4, 5, 6, 7, 8.
So you should not loop through d + 1. Use only d.
I'm trying to implement a simple elliptic curve encryption program but I can't get the expected output of doubling and adding a Point P till 12P .The curve equation isy^2 = x^3 +ax + b mod p. According to this site 3P = [10, 6] when P = [5, 1] while I get 3p = [10, 5]. The equations I use can be found on Wikipedia.
P = [5, 1]
prime = 17
a = 2
b = 2
def gcdExtended(a, b):
if a == 0:
return b, 0, 1
gcd, x1, y1 = gcdExtended(b % a, a)
x = y1 - (b // a) * x1
y = x1
return gcd, x, y
def double_point(point: list):
x = point[0]
y = point[1]
s = ((3*(x**2)+a) * (gcdExtended(2*y, prime)[1])) % prime
newx = (s**2 - x - x) % prime
newy = (s * (x - newx) - y) % prime
return [newx, newy]
def add_points(P: list, Q: list):
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
s = ((y2 - y1) * ((gcdExtended(x2-x1, prime))[1] % prime)) % prime
newx = (s**2 - x1 - x2) % prime
newy = (s * (x1 - newx) - y1) % prime
return [newx, newy]
Q = P
index = 2
while True:
if Q[0] == P[0] and Q[1] == P[1]:
print("doubling")
Q = double_point(P)
else:
print("adding")
Q = add_points(Q, P)
if index == 12 :
break
print(f"{index}P = {Q}")
index += 1
If the point [5,1] is added successively, the following sequence is obtained:
1P = [ 5, 1]
2P = [ 6, 3]
3P = [10, 6]
4P = [ 3, 1]
5P = [ 9, 16]
6P = [16, 13]
7P = [ 0, 6]
8P = [13, 7]
9P = [ 7, 6]
10P = [ 7, 11]
11P = [13, 10]
12P = [ 0, 11]
13P = [16, 4]
14P = [ 9, 1]
15P = [ 3, 16]
16P = [10, 11]
17P = [ 6, 14]
18P = [ 5, 16]
19P = point at infinity
This can be verified e.g. here.
The problem in the posted code is that the method to determine the modular inverse, gcdExtended(a, b), is only valid for positive a and b. While in double_point and add_points b has the value prime (= 17 > 0), a can take negative values.
gcdExtended generally returns wrong values for negative a:
The modular inverse of 5 or -12 is 7: 5 x 7 mod17 = 35 mod17 = 1 and 7 x (-12) mod17 = -84 mod17 = 85 mod17 = 1.
The gcdExtended returns for these values: gcdExtended(5, 17)[1] = 7 (which is true) and gcdExtended(-12, 17)[1] = -7 (which is false).
To allow negative values for a, e.g. the following methods can be defined, see here:
def sign(x):
return 1 if x >= 0 else -1
def gcdExtendedGeneralized(a, b):
gcd, x1, y1 = gcdExtended(abs(a), b)
return gcd, (sign(a) * x1) % b, y1 % b
Replacing gcdExtended with gcdExtendedGeneralized in double_point and add_points provides the correct values (note that the current implementation does not consider the point at infinity).
You interchanged P and Q in add_points. Also a small simplification in your calculation of s:
def add_points(P: list, Q: list):
x1 = P[0]
y1 = P[1]
x2 = Q[0]
y2 = Q[1]
#s = ((y2 - y1) * ((gcdExtended(x2-x1, prime))[1] % prime)) % prime
s = (y2-y1) * (gcdExtended(x2-x1, prime)[1] % prime)
newx = (s**2 - x1 - x2) % prime
newy = (s * (x1 - newx) - y1) % prime
return [newx, newy]
Q = P
index = 2
while True:
if Q[0] == P[0] and Q[1] == P[1]:
print("doubling")
Q = double_point(P)
else:
print("adding")
Q = add_points(P, Q)
if index == 12 :
break
print(f"{index}P = {Q}")
index += 1
which results in
doubling
2P = [6, 3]
adding
3P = [10, 6]
adding
4P = [3, 1]
adding
5P = [9, 16]
adding
6P = [16, 13]
adding
7P = [0, 6]
adding
8P = [13, 8]
adding
9P = [8, 7]
adding
10P = [8, 10]
adding
11P = [13, 9]
adding
How to iterate through lists to accommodate for more number of element, if 'U' list had more elements?
Specifically, line below:
for i in range(u+1):
x_matrix[i] = [pow(x[i],U[0]),pow(x[i],U[1]),pow(x[i],U[2]),pow(x[i],U[3])]
Full code:
import numpy as np
x = [-3, -2, -1, 0, 1, 2, 3]
y = [0, -4, 0, 6, 8, 0,-24]
ys = []
def check(lst):
result = False;
if len(lst) > 0 :
result = all(elem == lst[0] for elem in lst)
if result is True:
print("All Elements in List are Equal")
print(lst)
else:
print("All Elements in List are Not Equal")
print(lst)
a = []
a = [j-i for i, j in zip(lst[:-1], lst[1:])]
ys.append(a)
check(a)
check(y)
u = len(ys)
print('\nThe coordinates results in {}-th order polynomial.\n'.format(u))
U = list(range(u+1))
list.reverse(U)
x_matrix = [None]*(u+1)
for i in range(u+1):
x_matrix[i] = [pow(x[i],U[0]),pow(x[i],U[1]),pow(x[i],U[2]),pow(x[i],U[3])]
y_matrix = [v for k,v in enumerate(y[0:u+1])]
# AX = Y, Ainv dot Y = X
A = np.array(x_matrix)
Y = np.array(y_matrix)
Ainv = np.linalg.inv(A)
X = Ainv.dot(Y)
print(X)
Thank you.
Here is one way to vectorize the for loop. The [None] and [:,None] are needed to make sure that the arrays have compatible shape.
import numpy as np
x = np.array([-3, -2, -1, 0, 1, 2, 3])
n = 5
x[:,None] ** np.arange(n+1,0,-1)[None]
# note that x[:,None].shape[1] == np.arange(n+1,0,-1)[None].shape[0]
print(x[:,None] ** np.arange(n+1,0,-1)[None])
[[ 729 -243 81 -27 9 -3]
[ 64 -32 16 -8 4 -2]
[ 1 -1 1 -1 1 -1]
[ 0 0 0 0 0 0]
[ 1 1 1 1 1 1]
[ 64 32 16 8 4 2]
[ 729 243 81 27 9 3]]
Do you want something like this?
for i in range(u+1):
x_matrix[i] = [pow(x[i], elem) for elem in U]
If yes, there is a better way. Why you don't try like this:
x_matrix = [[pow(x[idx_elem], elem) for elem in U] for idx_elem in range(u+1)]
Is it possible to do magic squares with the Siamese/De La Loubere method without using modulo?
I would like to make odd n x n magic squares using it.
Yes, it's possible. Written on Python 3.5:
def siamese_method(n):
assert(n % 2 != 0), 'Square side size should be odd!'
square = [[0 for x in range(n)] for x in range(n)]
x = 0
y = int((n + 1) / 2 - 1)
square[x][y] = 1
for i in range(2, n * n + 1):
x_old = x
y_old = y
if x == 0:
x = n - 1
else:
x -= 1
if y == n - 1:
y = 0
else:
y += 1
while square[x][y] != 0:
if x == n - 1:
x = 0
else:
x = x_old + 1
y = y_old
square[x][y] = i
for j in square:
print(j)
siamese_method(3)
I've got following on output:
[8, 1, 6]
[3, 5, 7]
[4, 9, 2]