I have a rather simple system of equations of the form:
1*A + 0*B + x2*C + y2*D = x1
0*A + 1*B + y2*C + x2*D = y1
where the pairs (x1,y1) and (x2,y2) are known floats of length N (the system is over-determined), and I need to solve for the A, B, C, D parameters.
I've been playing around with numpy.linalg.lstsq but I can't seem to get the shapes of the matrices right. This is what I have
import numpy as np
N = 10000
x1, y1 = np.random.uniform(0., 5000., (2, N))
x2, y2 = np.random.uniform(0., 5000., (2, N))
# 1*A + 0*B + x2*C + y2*D = x1
# 0*A + 1*B + y2*C + x2*D = y1
l1 = np.array([np.ones(N), np.zeros(N), x2, y2])
l2 = np.array([np.zeros(N), np.ones(N), y2, x2])
M1 = np.array([l1, l2])
M2 = np.array([x1, y1])
ABCD = np.linalg.lstsq(M1, M2)[0]
print(ABCD)
which fails with:
numpy.linalg.linalg.LinAlgError: 3-dimensional array given. Array must be two-dimensional
What am I doing wrong?
Keeping everything else fixed, changing M1 and M2 to
M1 = np.vstack([l1.T, l2.T])
M2 = np.concatenate([x1, y1])
should do the job.
Your concatenation is an issue and also the parameters for lstsq() have to be transposed.
M1 = np.hstack((l1,l2))
M2 = np.hstack((x1,x2))
ABCD = np.linalg.lstsq(M1.T,M2.T)[0]
Related
Here is the code:
Outputs = []
for X2, Y2 in X:
Color_Gradient = 0
Lowest = 0
for X1, Y1, grad in zip(Velocity_Momentum[:, 0], Velocity_Momentum[:, 1], Color):
XD = X2 - X1
YD = Y2 - Y1
Distance = math.sqrt((XD * XD) + (YD * YD))
if Lowest == 0 or Lowest > Distance:
Lowest = Distance
Color_Gradient = grad
Outputs.append(Color_Gradient)
print("X2 = ", X2, " Y2 = ", Y2, " Color = ", Color_Gradient)
Here X.shape = (572, 2) Velocity_Momentum = (1000000, 2) Color = (1000000,).
Please let me know how to make it faster. I have tried the code above and it is very very slow. That is not good since I am trying to get the result faster.
Please let me know.
It looks like you are using numpy arrays. With numpy, it is faster to use vectorized operations on whole arrays at the same time, compared to loops. It also usually gives cleaner code.
As I understand it, you want to extract the color corresponding to the smallest (euclidean) distance to a specific point.
Outputs = []
for X2, Y2 in X:
XD = X2 - Velocity_Momentum[:, 0]
YD = Y2 - Velocity_Momentum[:, 1]
Distance = (XD * XD) + (YD * YD)
Color_Gradient = Color[Distance.argmin()]
Outputs.append(Color_Gradient)
print("X2 = ", X2, " Y2 = ", Y2, " Color = ", Color_Gradient)
I am trying to create the equation in python.
Sorry in advance if this has already been asked! If so, I couldn't find it, so please share the post!
I run into the problem that I don't know how to code the part in the red square (see equation ).
As I understand it the "|u1|" stands for the absolute value of u1. However, if I code it like the equation is written i.e. abs(u1)abs(u2) I get a syntax error (which I kind of expected).
My problem is the line of code:
angle = np.arccos((Mu1*Mu2)/(abs(Mu1)abs(Mu2)))
My complete code is:
import numpy as np
from math import sqrt
#first direction vector
#punt 1, PQ
# [x,y]
P = (1,1)
Q = (5,3)
#punt 2, RS
R = (2,3)
S = (4,1)
#direction vector = arctan(yq-yp/xq-xp)
#create function to calc direction vector of line
def dirvec(coord1, coord2):
#pull coordinates into x and y variables
x1 , y1 = coord1[0], coord1[1]
x2 , y2 = coord2[0], coord2[1]
#calc vector see article
v = np.arctan((y2-y1)/(x2-x1))
#outputs in radians, not degrees
v = np.degrees(v)
return v
print(dirvec(P,Q))
print(dirvec(R,S))
Mu1 = dirvec(P,Q)
Mu2 = dirvec(R,S)
angle = np.arccos((Mu1*Mu2)/(abs(Mu1)abs(Mu2)))
print(angle)
Thins I tried:
multiply the two abs, but then I'll get the same number (pi) every time:
np.arccos((Mu1*Mu2)/(abs(Mu1)*abs(Mu2)))
+ and - but I cannot imagine these are correct:
np.arccos((Mu1Mu2)/(abs(Mu1)+abs(Mu2))) np.arccos((Mu1Mu2)/(abs(Mu1)-abs(Mu2)))
In the formula, the numerator is the dot product of two vectors, and the denominator is the product of the norms of the two vectors.
Here is a simple way to write your formula:
import math
def dot_product(u, v):
(x1, y1) = u
(x2, y2) = v
return x1 * x2 + y1 * y2
def norm(u):
(x, y) = u
return math.sqrt(x * x + y * y)
def get_angle(u, v):
return math.acos( dot_product(u,v) / (norm(u) * norm(v)) )
def make_vector(p, q):
(x1, y1) = p
(x2, y2) = q
return (x2 - x1, y2 - y1)
#first direction vector
#punt 1, PQ
# [x,y]
P = (1,1)
Q = (5,3)
#punt 2, RS
R = (2,3)
S = (4,1)
angle = get_angle(make_vector(p,q), make_vector(r,s))
print(angle)
From what I see, the result of your code would always be pi or 0. It will be pi if one of the mu1 or mu2 is negative and when both are negative or positive it will be zero.
If I remember vectors properly :
Given two vectors P and Q, with say P = (x, y) and Q = (a, b)
Then abs(P) = sqrt(x^2 + y^2) and P. Q = xa+yb. So that cos# = P. Q/(abs(P) *abs(Q)). If am not clear you can give an example of what you intend to do
Okay so apparently I made a mistake in my interpretation.
I want to thank everyone for your solutions!
After some puzzling it appears that:
import math
import numpy as np
#punt 1, PQ
# [x,y]
P = (1,1)
Q = (5,3)
x1 = P[0]
x2 = Q[0]
y1 = P[1]
y2 = Q[1]
#punt 2, RS
R = (0,2)
S = (4,1)
x3 = R[0]
x4 = S[0]
y3 = R[1]
y4 = S[1]
angle = np.arccos(((x2 - x1) * (x4 - x3) + (y2 - y1) * (y4 - y3)) / (math.sqrt((x2 - x1)**2 + (y2 - y1)**2) * math.sqrt((x4 - x3)**2 + (y4 - y3)**2)))
print(angle)
Is the correct way to calculate the angle between two vectors.
This is obviously not pretty code, but it is the essence of how it works!
Again I want to thank you all for you reaction and solutions!
How do I implement bilinear interpolation for image data represented as a numpy array in python?
I found many questions on this topic and many answers, though none were efficient for the common case that the data consists of samples on a grid (i.e. a rectangular image) and represented as a numpy array. This function can take lists as both x and y coordinates and will perform the lookups and summations without need for loops.
def bilinear_interpolate(im, x, y):
x = np.asarray(x)
y = np.asarray(y)
x0 = np.floor(x).astype(int)
x1 = x0 + 1
y0 = np.floor(y).astype(int)
y1 = y0 + 1
x0 = np.clip(x0, 0, im.shape[1]-1);
x1 = np.clip(x1, 0, im.shape[1]-1);
y0 = np.clip(y0, 0, im.shape[0]-1);
y1 = np.clip(y1, 0, im.shape[0]-1);
Ia = im[ y0, x0 ]
Ib = im[ y1, x0 ]
Ic = im[ y0, x1 ]
Id = im[ y1, x1 ]
wa = (x1-x) * (y1-y)
wb = (x1-x) * (y-y0)
wc = (x-x0) * (y1-y)
wd = (x-x0) * (y-y0)
return wa*Ia + wb*Ib + wc*Ic + wd*Id
I'm implementing Runge–Kutta fourth-order method for system of two equations.
h is number of segments, so T/h is step.
def cauchy(f1, f2, x10, x20, T, h):
x1 = [x10]
x2 = [x20]
for i in range(1, h):
k11 = f1((i-1)*T/h, x1[-1], x2[-1])
k12 = f2((i-1)*T/h, x1[-1], x2[-1])
k21 = f1((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k11, x2[-1] + T/h/2*k12)
k22 = f2((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k11, x2[-1] + T/h/2*k12)
k31 = f1((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k21, x2[-1] + T/h/2*k22)
k32 = f2((i-1)*T/h + T/h/2, x1[-1] + T/h/2*k21, x2[-1] + T/h/2*k22)
k41 = f1((i-1)*T/h + T/h, x1[-1] + T/h*k31, x2[-1] + T/h*k32)
k42 = f2((i-1)*T/h + T/h, x1[-1] + T/h*k31, x2[-1] + T/h*k32)
x1.append(x1[-1] + T/h/6*(k11 + 2*k21 + 2*k31 + k41))
x2.append(x2[-1] + T/h/6*(k12 + 2*k22 + 2*k32 + k42))
return x1, x2
Then I'm testing it on this system:
def f1(t, x1, x2):
return x2
def f2(t, x1, x2):
return -x1
def true_x1(t):
return np.cos(t) + np.sin(t)
def true_x2(t):
return np.cos(t) - np.sin(t)
It seems to be working fine (I also tested it with different initial values and different functions: all works fine):
x10 = 1
x20 = 1
T = 1
h = 10
x1, x2 = cauchy(f1, f2, x10, x20, T, h)
t = np.linspace(0, T, h)
plt.xlabel('t')
plt.ylabel('x1')
plt.plot(t, true_x1(t), "blue", label="true_x1")
plt.plot(t, x1, "red", label="approximation_x1")
plt.legend(bbox_to_anchor=(0.97, 0.27))
plt.show()
plt.xlabel('t')
plt.ylabel('x2')
plt.plot(t, true_x2(t), "blue", label="true_x2")
plt.plot(t, x2, "red", label="approximation_x2")
plt.legend(bbox_to_anchor=(0.97, 0.97))
plt.show()
Then I want to check if the error is on the order of O(step^4), so I reduce step and compute error like this:
step = []
x1_error = []
x2_error = []
for segm in reversed(range(10, 1000)):
x1, x2 = cauchy(f1, f2, x10, x20, T, segm)
t = np.linspace(0, T, segm)
step.append(1/segm)
x1_error.append(np.linalg.norm(x1 - true_x1(t), np.inf))
x2_error.append(np.linalg.norm(x2 - true_x2(t), np.inf))
And I get this:
plt.plot(step, x1_error, label="x1_error")
plt.plot(step, x2_error, label="x2_error")
plt.legend()
So, the error is linear from step. This is really strange, because it is supposed to be on the order of O(step^4). Can anyone tell me what I did wrong?
for i in range(1, h):
This will iterate from 1 to h-1. As the last step is missing, the difference from x[h-1] at time T-T/h to the exact solution at time T is O(T/h).
Thus use
for i in range(1,h+1):
for h steps from i-1 to i or
for i in range(h):
for h steps from i to i+1.
Also, np.linspace(0,1,4) will produce 4 equally spaced numbers where the first is 0 and the last is 1, resulting in
array([ 0. , 0.33333333, 0.66666667, 1. ])
which is probably not what you were expecting. Thus with the above correction use
t = np.linspace(0, T, segm+1)
to use the same time points in both computations.
It would be easier to follow your code if you would use the letters in their usual meaning, where h or dt is the step size and N is the number of steps. Then define before the loop h=T/N or dt=T/N to avoid the repeated use of T/N in the function calls.
Let us assume I have a set of differential equations to be integrated with scipy odeint. Now my goal is to find the steady-state (I chose initial conditions such that this state exists). At the moment I have implemented something like
cond = True
while cond:
x = integrate(interval = [0,t], steps = 200)
if var(x[-22::]) < maxvar:
cond = False
return mean(x)
else:
t*= 2
Do you have a more efficient approach?
If you are using odeint, then you already have your differential equations written as a function f(x, t) (or possibly f(x, t, *args)). If your system is autonomous (i.e. f does not actually depend on t), you can find an equilibrium by solving f(x, 0) == 0 for x. You can use, for example, scipy.optimize.fsolve to solve for the equilibrium.
The following is an example. It uses the "Coupled Spring Mass System" example from the scipy cookbook. scipy.optimize.fsolve is used to find the equilibrium solution x1 = 0.5, y1 = 0, x2 = 1.5, y2 = 0.
from scipy.optimize import fsolve
def vectorfield(w, t, p):
"""
Defines the differential equations for the coupled spring-mass system.
Arguments:
w : vector of the state variables:
w = [x1, y1, x2, y2]
t : time
p : vector of the parameters:
p = [m1, m2, k1, k2, L1, L2, b1, b2]
"""
x1, y1, x2, y2 = w
m1, m2, k1, k2, L1, L2, b1, b2 = p
# Create f = (x1', y1', x2', y2'):
f = [y1,
(-b1 * y1 - k1 * (x1 - L1) + k2 * (x2 - x1 - L2)) / m1,
y2,
(-b2 * y2 - k2 * (x2 - x1 - L2)) / m2]
return f
if __name__ == "__main__":
# Parameter values
# Masses:
m1 = 1.0
m2 = 1.5
# Spring constants
k1 = 8.0
k2 = 40.0
# Natural lengths
L1 = 0.5
L2 = 1.0
# Friction coefficients
b1 = 0.8
b2 = 0.5
# Pack up the parameters and initial conditions:
p = [m1, m2, k1, k2, L1, L2, b1, b2]
# Initial guess to pass to fsolve. The second and fourth components
# are the velocities of the masses, and we know they will be 0 at
# equilibrium. For the positions x1 and x2, we'll try 1 for both.
# A better guess could be obtained by solving the ODEs for some time
# interval, and using the last point of that solution.
w0 = [1.0, 0, 1.0, 0]
# Find the equilibrium
eq = fsolve(vectorfield, w0, args=(0, p))
print "Equilibrium: x1 = {0:.1f} y1 = {1:.1f} x2 = {2:.1f} y2 = {3:.1f}".format(*eq)
The output is:
Equilibrium: x1 = 0.5 y1 = 0.0 x2 = 1.5 y2 = 0.0
Referring to your comments, I don't see any better way:
In this case where you know approximately where the system will settle.
(This is fairly easy to predict in some systems, like a pendulum, or a charging capacitor), and that it will settle, the fastest way I know is to check if
(p[0] * x[i] + p[1] * x[i-1] ... + p[n] * x[i-n] - mean(x[i-0:n]) )< epsilon)
The difficulty is determining the size of epsilon, the parameters p[0:n] to tune this detection.
Clearly you are already using this window method:
epsilon = varmax
p[0:n] = 1
n = 22
and have optimized it by removing the parameters for the filter, and simply using the variance.
For many systems (where settling looks like 1 order differential equations) the filter parameters turn out to look like this:
p[0] = n/2
p[n] = n/2
p[1:n-1] = 0
meaning you can make stuff go faster if you replace the calculation of state variance with this simple test:
if( abs(x[-22] - x[0]) > epsilon)
This will not detect correctly if small disturbances are still present, since we don't know your system, that's difficult to talk about...