Why is this source code plotting only two points? - python

Draw 10,000 points on the plane so that both the x and y coordinates of each point are in the range [-1, 1].
Print the coordinates of only those points which are contained in a circle with radius r0 = 1.0.
def nextRandom(seed):
m = 233280 # modulus
a = 9301 # multiplier
c = 49297 # increment
x0 = seed # start-value
return 2*(((a * x0 + c) % m)/m)-1 # between [-1, 1]
N = 10
x = [0]*N
y = [0]*N
p = [0]*N
x0 = 1
y0 = 0
r = 1.0
for i in range(1, N, 1):
x[i] = nextRandom(x0)
y[i] = nextRandom(x[i])
p[i] = x[i] * x[i] + y[i] * y[i]
if(p[i]<=r*r):
print(i, "(", "{0:.2f}, ".format(x[i]), "{0:.2f}".format(y[i]), ")")
import matplotlib.pyplot as plt
plt.scatter(x, y)
plt.show()
Output
In [33]: runfile('C:/Users/pc/Desktop/temp.py', wdir='C:/Users/pc/Desktop/')
1 ( -0.50, -0.62 )
2 ( -0.50, -0.62 )
3 ( -0.50, -0.62 )
4 ( -0.50, -0.62 )
5 ( -0.50, -0.62 )
6 ( -0.50, -0.62 )
7 ( -0.50, -0.62 )
8 ( -0.50, -0.62 )
9 ( -0.50, -0.62 )
Why is this source code plotting only two points?
Edit: modified the code as follows:
for i in range(1, N, 1):
x[i] = nextRandom(x0)
x0 = x[i] ##<=========================added this line
y[i] = nextRandom(x[i])
p[i] = x[i] * x[i] + y[i] * y[i]
if(p[i]<=r*r):
print(i, "(", "{0:.2f}, ".format(x[i]), "{0:.2f}".format(y[i]), ")")
Output
1 ( -0.50, -0.62 )
2 ( -0.62, -0.63 )
3 ( -0.63, -0.63 )
4 ( -0.63, -0.63 )
5 ( -0.63, -0.63 )
6 ( -0.63, -0.63 )
7 ( -0.63, -0.63 )
8 ( -0.63, -0.63 )
9 ( -0.63, -0.63 )
I am not seeing much improvement.

Looks like an issue with the proposed random number generation scheme. Instead of dividing by m in the nextRandom function, you can generate a bunch of pseudorandom integers between 0 and m, then rescale and plot.
# output ints!
def nextRandom(seed):
m = 233280 # modulus
a = 9301 # multiplier
c = 49297 # increment
x0 = seed # start-value
return ((a * x0 + c) % m)
# generate (hopefully) random ints
m = 233280
# initialize integer arrays to store iterative applications
# of nextRandom. Random seed for x is 0, random seed for y is 1
rx, ry = [0], [1]
for i in range(500):
rx.append(nextRandom(rx[-1]))
ry.append(nextRandom(ry[-1]))
# rescale to the 2x2 square around the origin
xs = [2*x/m-1 for x in rx]
ys = [2*y/m-1 for y in ry]
# different colors based on distance to the origin
color = ['red' if x**2 + y**2 < 1 else 'blue' for x, y in zip(xs, ys)]
from matplotlib import pyplot as plt
plt.scatter(xs, ys, c=color)
Results look like this:

Related

Numpy accurately computing the inverse of a matrix?

I am trying to compute the eigen values of a matrix built by a matrix product M^{-1}K.
I know M and K, I have initialized them properly. I thus try to compute the inverse of M:
M_inv = np.linalg.inv(M)
with np.printoptions(threshold=np.inf, precision=10, suppress=True,linewidth=20000):
print(np.matrix(M_inv * M))
That should print the identity, but I get:
Which clearly is not the identity. I need to find the eigen values of M_inv * K, but if M_Inv is so innacurate I won't get anything useful, what do I do?
This is the matrix:
And this is my initialization code:
def mij(i, j, h):
if i==j:
return 2.0 * h / 3.0
else:
return h / 6.0
def kij(i, j, h):
if i==j:
return 2.0 / h
else:
return -1 / h
n = 500
size=n+1
h = 1 / n
t=np.linspace(0,1,n)
# Get A
M = np.zeros((n, n))
K = np.zeros((n, n))
for i in range(0, n):
M[i,i] = mij(i, i, h)
if i+1 < n:
M[i,i+1] = mij(i, i+1, h)
if i-1 >= 0:
M[i,i-1] = mij(i, i-1, h)
K[i,i] = kij(i, i, h)
if i+1 < n:
K[i,i+1] = kij(i, i+1, h)
if i-1 >= 0:
K[i,i-1] = kij(i, i-1, h)
Try to compute the inverse column by column using this:
c1 = numpy.linalg.solve(M, [1, 0, ..., 0])
cn = numpy.linalg.solve(M, [0, ..., 0, 1])
An example with a tri-diagonal matrix in this code:
import numpy as np
M = np.array([[1,2,0],[1,4,9],[0,8,27]])
I = np.identity(3)
print(M)
#using inv
Minv1 = np.linalg.inv(M)
#using solve
Minv2 = list()
for i in range(3):
Minv2.append(np.linalg.solve(M, I[i]))
Minv2 = np.array([list(column) for column in zip(*Minv2)])
#same as:
Minv3 = np.linalg.solve(M, I)
print(Minv1)
print(Minv2)
print(Minv3)
Generated output:
[[ 1 2 0]
[ 1 4 9]
[ 0 8 27]]
[[-2. 3. -1. ]
[ 1.5 -1.5 0.5 ]
[-0.44444444 0.44444444 -0.11111111]]
[[-2. 3. -1. ]
[ 1.5 -1.5 0.5 ]
[-0.44444444 0.44444444 -0.11111111]]
[[-2. 3. -1. ]
[ 1.5 -1.5 0.5 ]
[-0.44444444 0.44444444 -0.11111111]]
The numpy.linalg.solve function is supposed to have a higher precission than the numpy.linalg.inv.
With n=5:
M = np.array([[1,2,0,0,0],[1,4,9,0,0],[0,8,27,1,0],[0,0,81,1,2],[0,0,0,1,23]])
I = np.identity(len(M))
print(M)
#using inv
Minv1 = np.linalg.inv(M)
#using solve
Minv2 = list()
for i in range(len(M)):
Minv2.append(np.linalg.solve(M, I[i]))
Minv2 = np.array([list(column) for column in zip(*Minv2)])
#same as:
Minv3 = np.linalg.solve(M, I)
print(Minv1)
print(Minv2)
print(Minv3)
Generated output:
[[ 1 2 0 0 0]
[ 1 4 9 0 0]
[ 0 8 27 1 0]
[ 0 0 81 1 2]
[ 0 0 0 1 23]]
[[ 1.63157895e+00 -6.31578947e-01 -9.21052632e-02 1.00877193e-01
-8.77192982e-03]
[-3.15789474e-01 3.15789474e-01 4.60526316e-02 -5.04385965e-02
4.38596491e-03]
[-4.09356725e-02 4.09356725e-02 -1.02339181e-02 1.12085770e-02
-9.74658869e-04]
[ 3.63157895e+00 -3.63157895e+00 9.07894737e-01 1.00877193e-01
-8.77192982e-03]
[-1.57894737e-01 1.57894737e-01 -3.94736842e-02 -4.38596491e-03
4.38596491e-02]]
[[ 1.63157895e+00 -6.31578947e-01 -9.21052632e-02 1.00877193e-01
-8.77192982e-03]
[-3.15789474e-01 3.15789474e-01 4.60526316e-02 -5.04385965e-02
4.38596491e-03]
[-4.09356725e-02 4.09356725e-02 -1.02339181e-02 1.12085770e-02
-9.74658869e-04]
[ 3.63157895e+00 -3.63157895e+00 9.07894737e-01 1.00877193e-01
-8.77192982e-03]
[-1.57894737e-01 1.57894737e-01 -3.94736842e-02 -4.38596491e-03
4.38596491e-02]]
[[ 1.63157895e+00 -6.31578947e-01 -9.21052632e-02 1.00877193e-01
-8.77192982e-03]
[-3.15789474e-01 3.15789474e-01 4.60526316e-02 -5.04385965e-02
4.38596491e-03]
[-4.09356725e-02 4.09356725e-02 -1.02339181e-02 1.12085770e-02
...
[ 3.63157895e+00 -3.63157895e+00 9.07894737e-01 1.00877193e-01
-8.77192982e-03]
[-1.57894737e-01 1.57894737e-01 -3.94736842e-02 -4.38596491e-03
4.38596491e-02]]

For loop to iterate the operation

import numpy as np
import pandas as pd
from scipy.spatial.distance import directed_hausdorff
df:
1 1.1 2 2.1 3 3.1 4 4.1
45.13 7.98 45.10 7.75 45.16 7.73 NaN NaN
45.35 7.29 45.05 7.68 45.03 7.96 45.05 7.65
Calculated distance for 1 couple
x = df['3']
y = df['3.1']
P = np.array([x, y])
q = df['4']
w = df['4.1']
Q = np.array([q, w])
Q_final = list(zip(Q[0], Q[1]))
P_final = list(zip(P[0], P[1]))
directed_hausdorff(P_final, Q_final)[0]
Desired output:
Same process with for loop for the whole dataset
distance from a['0'], a['0']is 0
from a['0'], a['1'] is 0.234 (some number)
from a['0'], a['2'] is .. ...
From [0] to all, then to [1] to all and etc.
Finally I should get a matrix with 0s` in diagonal
I Have tried:
space = list(df.index)
dist = []
for j in space:
for k in space:
if k != j:
dist.append((j, k, directed_hausdorff(P_final, Q_final)[0]))
But getting same value of distance between [3] and [4]
I am not entirely sure what you are trying to do.. but based on how you calculated the first one, here is a possible solution:
import pandas as pd
import numpy as np
from scipy.spatial.distance import directed_hausdorff
df = pd.read_csv('something.csv')
groupby = lambda l, n: [tuple(l[i:i+n]) for i in range(0, len(l), n)]
values = groupby(df.columns.values, 2)
matrix = np.zeros((4, 4))
for Ps in values:
x = df[str(Ps[0])]
y = df[str(Ps[1])]
P = np.array([x, y])
for Qs in values:
q = df[str(Qs[0])]
w = df[str(Qs[1])]
Q = np.array([q, w])
Q_final = list(zip(Q[0], Q[1]))
P_final = list(zip(P[0], P[1]))
matrix[values.index(Ps), values.index(Qs)] = directed_hausdorff(P_final, Q_final)[0]
print(matrix)
Output:
[[0. 0.49203658 0.47927028 0.46861498]
[0.31048349 0. 0.12083046 0.1118034 ]
[0.25179357 0.22135944 0. 0.31064449]
[0.33955854 0.03 0.13601471 0. ]]

How do i use two 2 dimentional arrays to form a 3 dimentional one without using loops in numpy?

Let A and B be two numpy arrays with shapes ( X , Y ) and ( Z , Y ) respectively. I need an array C with shape ( X , Y , Z) where, for every x , y and z, C[ x , y , z ] = A[ x , y ] - B[ z , y ].
The fastest way i know to compute C is to subtract B from every row of A, like in this sample of code.
import numpy
X , Y , Z = 10 , 8 , 3
A = numpy.random.rand( ( X , Y ) )
B = numpy.random.rand( ( Z , Y ) )
C = numpy.zeros( ( X , Y , Z ) )
for x in range( X ):
C[ x ] = A[ x ] - B
print( A , B , C , sep = "\n\n")
Is there any vectorized way to do this without needing to use loop, so the code could run faster?
I appreciate any help :)
This is called broadcasting, with B transformed:
C = A[:,:,None] - B.T[None,:,:]
C.shape
Output
(10, 8, 3)

linear interpolation between two data points

I have two data points x and y:
x = 5 (value corresponding to 95%)
y = 17 (value corresponding to 102.5%)
No I would like to calculate the value for xi which should correspond to 100%.
x = 5 (value corresponding to 95%)
xi = ?? (value corresponding to 100%)
y = 17 (value corresponding to 102.5%)
How should I do this using python?
is that what you want?
In [145]: s = pd.Series([5, np.nan, 17], index=[95, 100, 102.5])
In [146]: s
Out[146]:
95.0 5.0
100.0 NaN
102.5 17.0
dtype: float64
In [147]: s.interpolate(method='index')
Out[147]:
95.0 5.0
100.0 13.0
102.5 17.0
dtype: float64
You can use numpy.interp function to interpolate a value
import numpy as np
import matplotlib.pyplot as plt
x = [95, 102.5]
y = [5, 17]
x_new = 100
y_new = np.interp(x_new, x, y)
print(y_new)
# 13.0
plt.plot(x, y, "og-", x_new, y_new, "or");
We can easily plot this on a graph without Python:
This shows us what the answer should be (13).
But how do we calculate this? First, we find the gradient with this:
The numbers substituted into the equation give this:
So we know for 0.625 we increase the Y value by, we increase the X value by 1.
We've been given that Y is 100. We know that 102.5 relates to 17. 100 - 102.5 = -2.5. -2.5 / 0.625 = -4 and then 17 + -4 = 13.
This also works with the other numbers: 100 - 95 = 5, 5 / 0.625 = 8, 5 + 8 = 13.
We can also go backwards using the reciprocal of the gradient (1 / m).
We've been given that X is 13. We know that 102.5 relates to 17. 13 - 17 = -4. -4 / 0.625 = -2.5 and then 102.5 + -2.5 = 100.
How do we do this in python?
def findXPoint(xa,xb,ya,yb,yc):
m = (xa - xb) / (ya - yb)
xc = (yc - yb) * m + xb
return
And to find a Y point given the X point:
def findYPoint(xa,xb,ya,yb,xc):
m = (ya - yb) / (xa - xb)
yc = (xc - xb) * m + yb
return yc
This function will also extrapolate from the data points.

TypeError: only length-1 arrays can be converted to Python scalars when trying to plot in Notebook

Here's my code:
import random
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
nsim = 1000 # aantal simulaties
n = 5 # Aantal deuren
def simulate_prizedoor(nsim, n):
return np.random.randint(n, size=nsim)
prizedoors = simulate_prizedoor(nsim, n)
print "simulate_prizedoor(nsim = 1000, n = 30)=", prizedoors[:15]
def simulate_guess(nsim, n):
return np.random.randint(n, size=nsim)
guesses = simulate_guess(nsim, n)
print "simulate_guess(nsim = 1000, n = 30)=", guesses[:15]
def simulate_switch(prizedoor, guess, n):
switched_list = []
for sim in range(prizedoor.shape[0]):
while True:
randomInt = np.random.randint(n)
if randomInt != prizedoor[sim] and randomInt != guess[sim]:
switched_list.append(randomInt)
break
return np.array(switched_list)
print "simulate_switch(simulate_prizedoor(nsim = 10, n), simulate_guess(10, n), n) =", simulate_switch(simulate_prizedoor(10, n), simulate_guess(10, n), n)
def win_percentage(guesses, prizedoors):
win = float(0)
for sim in range(len(guesses)):
if guesses[sim] == prizedoors[sim]:
win += 1
win_perc = (win / len(guesses)) * 100
return win_perc
print "win_percentage(simulate_guess(nsim, n), simulate_prizedoor(nsim,n))=", win_percentage(simulate_guess(nsim, n), simulate_prizedoor(nsim,n))
print "win_percentage(simulate_switch(simulate_prizedoor(nsim, n), simulate_guess(nsim, n), n), simulate_prizedoor(nsim,n))=", win_percentage(simulate_switch(simulate_prizedoor(nsim, n), simulate_guess(nsim, n), n), simulate_prizedoor(nsim,n))
print "*** PLOT Intepr 1 ***"
x = np.linspace(0, 20)
y = win_percentage(simulate_switch(simulate_prizedoor(nsim, x), simulate_guess(nsim, x), x), simulate_prizedoor(nsim,x))
plt.plot(x, y)
plt.xlabel("X axis")
plt.ylabel("Y axis")
This is the output and the error:
simulate_prizedoor(nsim = 1000, n = 30)= [2 1 0 4 3 2 2 2 0 3 1 0 4 1 0]
simulate_guess(nsim = 1000, n = 30)= [2 0 1 3 1 3 1 4 3 2 0 0 3 4 2]
simulate_switch(simulate_prizedoor(nsim = 10, n), simulate_guess(10, n), n) = [2 3 0 3 4 2 1 3 1 1]
win_percentage(simulate_guess(nsim, n), simulate_prizedoor(nsim,n))= 18.9
win_percentage(simulate_switch(simulate_prizedoor(nsim, n), simulate_guess(nsim, n), n), simulate_prizedoor(nsim,n))= 21.4
*** PLOT Intepr 1 ***
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-1-55303947fa57> in <module>()
53
54 x = np.linspace(0, 20)
---> 55 y = win_percentage(simulate_switch(simulate_prizedoor(nsim, x), simulate_guess(nsim, x), x), simulate_prizedoor(nsim,x))
56
57 plt.plot(x, y)
<ipython-input-1-55303947fa57> in simulate_prizedoor(nsim, n)
10
11 def simulate_prizedoor(nsim, n):
---> 12 return np.random.randint(n, size=nsim)
13
14 prizedoors = simulate_prizedoor(nsim, n)
mtrand.pyx in mtrand.RandomState.randint (numpy/random/mtrand/mtrand.c:9533)()
TypeError: only length-1 arrays can be converted to Python scalars
I've tried to find a solution and I've rewritten most of the code. First I thought it was because im not using the NP random.randint to determine a random integer. I implemented that but the issue is still the same. Anyone here shed some light on what's exactly going wrong here?
Im trying to plot a graph in matplotlib. With on the y-axis the winpercentage and on the horintal: n.
Feedback appriciated!
The problem is you're trying to pass an array "x = np.linspace(0,20)" to the function np.random.randint( x, size). You need to pass single integer values to this function.

Categories

Resources