Can't figure out a recursive function - python

I have this piece of code to calculate first and second derivatives of a function at a given point
def yy(x):
return 1.0*x*x
def d1(func, x ,e):
x = x
y = func(x)
x1 = x + e
y1 = func(x1)
return 1.0*(y - y1)/(x - x1)
def d2(func ,x, e):
x = x
y = d1(func, x, e)
x1 = x + e
y1 = d1(func, x1, e)
return 1.0*(y - y1)/(x - x1)
yy is the actual function. d1 and d2 functions that calculate the 1st and 2nd derivatives. They are the ones I'm interested in optimizing. As you can see they both have almost the same code. I could basically keep writing functions like that for 3rd, 4th, etc derivatives, however I'm wondering if it is possible to write it as a single function specifying the derivative level as a parameter.

def deriv(func, order, x, e):
if order < 0: raise ValueError
if order == 0: return func(x)
y = deriv(func, order-1, x, e)
x1 = x + e
y1 = deriv(func, order-1, x1, e)
return float(y - y1)/(x - x1)
order = 1 gives the first derivative, order = 2 gives the 2nd, and so on.

Try this, where lvl is derivative level.
def d(func, x ,e, lvl):
x1 = x + e
if lvl == 1:
x = x
y = func(x)
y1 = func(x1)
return 1.0*(y - y1)/(x - x1)
else:
return 1.0*(d(func, x, e, lvl-1) - d(func, x1, e, lvl-1) )/(x-x1)

Related

How to Solve for the Motion of a Double Pendulum

I want to plot the motion of a double pendulum with a spring in python. I need to plot the theta1, theta2, r, and their first derivatives. I have found my equations for the motion, which are second-order ODEs so I then converted them to first-order ODEs where x1=theta1, x2=theta1-dot, y1=theta2, y2=theta2-dot, z1=r, and z2=r-dot. Here is a picture of the double pendulum problem: enter image description here
Here is my code:
from scipy.integrate import solve_ivp
from numpy import pi, sin, cos, linspace
g = 9.806 #Gravitational acceleration
l0 = 1 #Natural length of spring is 1
k = 2 #K value for spring is 2
OA = 2 #Length OA is 2
m = 1 #Mass of the particles is 1
def pendulumDynamics1(t, x): #Function to solve for theta-1 double-dot
x1 = x[0]
x2 = x[1]
y1 = y[0]
y2 = y[1]
z1 = z[0]
z2 = z[1]
Fs = -k*(z1-l0)
T = m*(x2**2)*OA + m*g*cos(x1) + Fs*cos(y1-x1)
x1dot = x2
x2dot = (Fs*sin(y1-x1) - m*g*sin(x1))/(m*OA) # angles are in radians
return [x1dot,x2dot]
def pendulumDynamics2(t, y): #Function to solve for theta-2 double-dot
x1 = x[0]
x2 = x[1]
y1 = y[0]
y2 = y[1]
z1 = z[0]
z2 = z[1]
Fs = -k*(z1-l0)
y1dot = y2
y2dot = (-g*sin(y1) - (Fs*cos(y1-x1)*sin(x1))/m + g*cos(y1-x1)*sin(x1) - x2*z1*sin(x1))/z1
return [y1dot,y2dot]
def pendulumDynamics3(t, z): #Function to solve for r double-dot (The length AB which is the spring)
x1 = x[0]
x2 = x[1]
y1 = y[0]
y2 = y[1]
z1 = z[0]
z2 = z[1]
Fs = -k*(z1-l0)
z1dot = z2
z2dot = g*cos(y1) - Fs/m + (y2**2)*z1 + x2*OA*cos(y1-x1) - (Fs*(sin(y1-x1))**2)/m + g*sin(x1)*sin(y1-x1)
return [z1dot,z2dot]
# Define initial conditions, etc
d2r = pi/180
x0 = [30*d2r, 0] # start from 30 deg, with zero velocity
y0 = [60*d2r, 0] # start from 60 deg, with zero velocity
z0 = [1, 0] #Start from r=1
t0 = 0
tf = 10
#Integrate dynamics, initial value problem
sol1 = solve_ivp(pendulumDynamics1,[t0,tf],x0,dense_output=True) # Save as a continuous solution
sol2 = solve_ivp(pendulumDynamics2,[t0,tf],y0,dense_output=True) # Save as a continuous solution
sol3 = solve_ivp(pendulumDynamics3,[t0,tf],z0,dense_output=True) # Save as a continuous solution
t = linspace(t0,tf,200) # determine solution at these times
dt = t[1]-t[0]
x = sol1.sol(t)
y = sol2.sol(t)
z = sol3.sol(t)
I have 3 functions in my code, each to solve for x, y, and z. I then use solve_ivp function to solve for x, and y, and z. The error in the code is:
`File "C:\Users\omora\OneDrive\Dokument\AERO 211\project.py", line 13, in pendulumDynamics1
y1 = y[0]
NameError: name 'y' is not defined`
I don't understand why it is saying that y is not defined, because I defined it in my functions.
Your system is closed without friction, thus can be captured by the Lagrange or Hamiltonian formalism. You have 3 position variables, thus a 6-dimensional dynamical state, complemented either by the velocities or the impulses.
Let q_k be theta_1, theta_2, r, Dq_k their time derivatives and p_k the impulse variables to q_k, then the dynamics can be realized by
def DoublePendulumSpring(u,t,params):
m_1, l_1, m_2, l_2, k, g = params
q_1,q_2,q_3 = u[:3]
p = u[3:]
A = [[l_1**2*(m_1 + m_2), l_1*m_2*q_3*cos(q_1 - q_2), -l_1*m_2*sin(q_1 - q_2)],
[l_1*m_2*q_3*cos(q_1 - q_2), m_2*q_3**2, 0],
[-l_1*m_2*sin(q_1 - q_2), 0, m_2]]
Dq = np.linalg.solve(A,p)
Dq_1,Dq_2,Dq_3 = Dq
T1 = Dq_2*q_3*sin(q_1 - q_2) + Dq_3*cos(q_1 - q_2)
T3 = Dq_1*l_1*cos(q_1 - q_2) + Dq_2*q_3
Dp = [-l_1*(m_2*Dq_1*T1 + g*(m_1+m_2)*sin(q_1)),
l_1*m_2*Dq_1*T1 - g*m_2*q_3*sin(q_2),
m_2*Dq_2*T3 + g*m_2*cos(q_2) + k*(l_2 - q_3) ]
return [*Dq, *Dp]
For a derivation see the Euler-Lagrange equations and their connection to the Hamilton equations. You might get asked about such a derivation.
This, after suitable defining the parameter tuple and initial conditions, can be fed to odeint and produces a solution that can then be plotted, animated or otherwise examined. The lower bob traces a path like the one below, not periodic and not very deterministic. (The fulcrum and the arc of the upper bob are also inserted, but less interesting.)
def pendulumDynamics1(t, x):
x1 = x[0]
x2 = x[1]
y1 = y[0]
y2 = y[1]
z1 = z[0]
z2 = z[1]
You only pass x as a parameter. The code inside the function has no idea what y and z refer to.
You will need to change the function call to also include those variables.
def pendulumDynamics1(t, x, y, z):

Distance from point to two line segments

I'm rather new to coding and am trying to check whether a dot drawn (in pygame)is on the last line drawn (making the sprouts game).
I have two lists, both holding coordinates of the line segments (in 30pix) just drawn, and one with last dot drawn.
current_line = []
dot_pos = []
Distance function I found online:
def dist_point_to_line(line1, line2, point):
x0 = point[0]
y0 = point[1]
x1 = line1[0]
y1 = line1[1]
x2 = line2[0]
y2 = line2[1]
px = x2-x1
py = y2-y1
norm = px*px + py*py
u = ((x0 - x1) * px + (y0 - y1) * py) / float(norm)
if u > 1:
u = 1
elif u < 0:
u = 0
x = x1 + u * px
y = y1 + u * py
dx = x - x0
dy = y - y0
dist = sqrt(dx*dx + dy*dy)
return dist
Now I want to implement the check at each segment of the line, but I'm stuck. Any advice?
This is what I thought of, though it doesn't want to work:
def distance_check():
for i in range(len(current_line)-1):
if dist_point_to_line(current_line[i], current_line[i+1], dot_pos) < 10:
return True #dot allowed to be placed
return False
If dot_pos is a list then you have to get the last element of the list (dot_pos[-1]). Note the arguments to the function dist_point_to_line are single dots, rather than a list of dots:
def distance_check():
for i in range(len(current_line)-1):
if dist_point_to_line(current_line[i], current_line[i+1], dot_pos[-1]) < 10:
return True #dot allowed to be placed
return False

function to find roots through Newton's method and calling it to solve general equation

I have written this function for newton's method
#root_Newton.py
def root_newton ( f, df, guess, tolerance = 1.0e-6):
dx = 2 * tolerance
while dx > tolerance:
x1 = x - f(x)/df(x)
dx = abs (x - x1)
x = x1
return x
and calling it to solve a quadratic equation
from math import *
from root_Newton import root_newton
def function(x):
x = x**2 - 1*x -6
return x
def derivative(dx):
dx = 2*x - 1
return dx
func = root_newton (function , derivative , 1.7)
print 'Found f(x) =0 at x = %0.8f +/- %0.8f' % ( func , tolerance)
and getting the error
File "quadfromnewtonsroot.py", line 11, in <module>
func = root_newton (function , derivative , 1.7)
File "/home/trina/Pictures/python/root_Newton.py", line 4, in root_newton
x1 = x - f(x)/df(x)
UnboundLocalError: local variable 'x' referenced before assignment
please help me fix the error, thnks
You had variables that were not defined in the scope they were being used:
def root_newton (f, df, guess, epsilon=1.0e-6):
""" calculates the root of the given equation
to within epsilon, using Newton's method
returns the root if found
"""
dx = 2 * epsilon
x = guess #<--- your need to initialize x to the value of guess
while dx > epsilon:
x1 = x - f(x)/df(x)
dx = abs(x - x1)
x = x1
return x
def function(x):
"""Evaluates the function at x
returns the value found
"""
return x**2 - 1*x - 6
def derivative(x):
"""Evaluates the derivative at x
returns the value found
"""
return 2*x - 1
root = root_newton(function, derivative, 1.7)
epsilon = 1.0e-6 #<--- you need to define epsilon in this scope to be able to print it
print 'Found f(x) = 0 at x = %0.8f +/- %0.8f' % (root, epsilon)
Output
Found f(x) = 0 at x = 3.00000000 +/- 0.00000100

How do I call a function?

I am trying to make a program that solves math equations. I want it to ask what type of question would you like to solve, then based on the answer, it then directs you to a function that I created. the function will ask you the values of some variables, and it will then solve the question.
What_do_you_need = raw_input("Which equation would you like to use?")
if What_do_you_need == "find_Y_value":
slope = int(raw_input("Enter the slope"))
X = int(raw_input("Enter the X coordinate"))
Y_int = int(raw_input("Enter the Y intercept"))
import find_Y_value
def find_Y_value(slope, X, Y_int):
Y = (slope * X) + Y_int
print(Y)
def find_Y_int(Y, slope, X):
Y_int = (slope * X) - Y
print(Y_int)
def find_X_value(Y, slope, Y_int):
X_value = (Y-Y_int)/slope
print(X_value)
def Slope_from_Slope_int(Y, X, Y_int):
slope = (Y-Y_int)/X
print(slope)
def Slope_from_Coordinates(X1, X2, Y1, Y2):
slope1 = (Y2 - Y1)/(X2 - X1)
print(slope1)
If I properly understand your goal, to call the function you would replace import find_Y_value with:
find_Y_value(slope, X, Y_int)
and move the definitions above the place where you call them, or they will not have been defined yet.

Karatsuba algorithm incorrect result

I just simply followed the pseudo code on wiki http://en.wikipedia.org/wiki/Karatsuba_algorithm
But the result of this implementation is very unstable.
It works sometimes but in case like 100*100. It does fail. What I missed here? please take a look.
from math import *
f = lambda x: (int(x) & 1 and True) and 1
def fast_multiply( x = "100", y = "100"):
print "input "+x+" | "+y
int_buff = map( int, [x, y])
if int_buff[0] < 10 or int_buff[1] < 10:
#print "lol"
return int_buff[0]*int_buff[1]
degree = max( x.__len__(), y.__len__())
higher_x, lower_x = x[ : int( ceil( len(x) / 2.0))], x[ len(x)/2 +f(len(x)):]
higher_y, lower_y = y[ : int( ceil( len(y) / 2.0))], y[ len(y)/2 +f(len(y)):]
#print lower_x+" & "+lower_y
z0 = fast_multiply(lower_x, lower_y) #z0 = 0
z1 = fast_multiply(str(int(lower_x)+int(higher_x)), str(int(lower_y)+int(higher_y)))
z2 = fast_multiply(higher_x, higher_y)
print "debug "+str(z0)+" "+str(z1)+" "+str(z2)
return z2*(10**degree) + (z1-z2-z0)*(10**(degree/2))+z0
if __name__ == '__main__':
print fast_multiply()
I have noticed in the case 100*100 z2 will be 100 which is correct. This gives z2*(10**3)=100000 which is definitely wrong...
The pseudocode you used was wrong. The problem was in z2*(10**degree). You should have raised the base to 2*m where m is what you meant to calculate with int( ceil(len(x) / 2.0)) (len(x) and len(y) should both have been degree).
I couldn't resist refactoring it... a little. I used the names from the definitions on the wiki. It would be straightforward to implement it with an arbitrary base, but I stuck with 10 for simplicity.
def kmult(x, y):
if min(x, y) < 10:
return x * y
m = half_ceil(degree(max(x, y)))
x1, x0 = decompose(x, m)
y1, y0 = decompose(y, m)
z2 = kmult(x1, y1)
z0 = kmult(x0, y0)
z1 = kmult(x1 + x0, y1 + y0) - z2 - z0
xy = z2 * 10**(2*m) + z1 * 10**m + z0
return xy
def decompose(x, m):
return x // 10 ** m, x % 10 ** m
def degree(x):
return len(str(x))
def half_ceil(n):
return n // 2 + (n & 1)
Testing:
print kmult(100, 100)
def test_kmult(r):
for x, y in [(a, b) for b in range(r+1) for a in range(r+1)]:
if kmult(x, y) != x * y:
print('fail')
break
else:
print('success')
test_kmult(100)
Result:
10000
success

Categories

Resources