The equation requires the previous output to calculate the next value.
Vi = V(i-1) + t((c*(V(i-1)^2)/m)-g). With V(0)=0 and all other values being defined I am not sure how to write a loop code that would store the previous value and then calculate the next iteration. I've tried a def approach but I could never figure out how to recall the previous calculation to use in the next step.
Vi = Vo + Dt*((c*(Vo**2)/m)-g)
return Vi
A recursive solution, where you define each value of v relative to the prior value, might look like this:
def calculate_v(i):
if i == 0:
return 0
v = calculate_v(i - 1)
return v + t * (c * v ** 2 / m - g)
whereas an iterative solution, where you just re-calculate v i times, would look like:
def calculate_v(i):
v = 0
for _ in range(i):
v = v + t * (c * v ** 2 / m - g)
return v
Assuming t, c, m, and g are constants you can pass them to the recursive function:
def V(input, t, c, m, g) -> int:
if input == 0: return 0
return V(input - 1, t, c, m, g) + t( (c * (V(input - 1, t, c, m, g) ** 2) / m) -g)
t=time, c = a constant, m=mass, g=gravity. c, m, g are universal constants; the initial condition is Vo.
You are updating the time. t here is a list.
Let's say t = [i for i in range(10)].
Your goal is to get V[i], which is a list of velocity at time t[i]. You can use a simple for loop:
Step 1:
Initialize V to be a list of zeros first.
V = [0]*len(t)
Step 2:
Calculate and populate V using a for loop.
for i in range(0, len(t)):
V[i] = Vo + Dt[i]*((c*(Vo**2)/m)-g)
Step 3:
return V
Therefore if you want to use def, it would be:
def calculate_V(t):
V = [0]*len(t)
for i in range(0, len(t)):
V[i] = Vo + Dt[i]*((c*(Vo**2)/m)-g)
return V
Related
Note: I am not that experienced in Python, therefore my code may not be as good as it could/should be.
I am attempting to create a tool to facilitate calculating the algebraic factors of a certain form of number (see https://en.wikipedia.org/wiki/Aurifeuillean_factorization). This is mostly as a test/learning experience, however I have run into a problem when attempting to calculate the parameter "c", which is defined as 2^(2k+1)+1. The addition step does not work for me. I am simply getting the returned value as 2^129, instead of 2^129+1 as I am looking to get. Is this an issue with Python itself, or am I making some sort of mistake in this.
Code:
import math
def make_aurifeuille_factors(base, exponent):
if base == 2 and exponent % 4 == 2:
k = (exponent - 2) / 4
c = int(1 + 2 ** (2*k + 1))
d = int(2 ** (k + 1))
L = c + d
M = c - d
return int(k), int(c), int(d), int(L), int(M)
def gcd(a, b):
return int(math.gcd(a, b))
print(make_aurifeuille_factors(2, 258))
k = (exponent - 2) / 4 makes k a float, which means you potentially introduce numerical error in computations down the line. Use integer division to stay in int world from the start:
def make_aurifeuille_factors(base, exponent):
if base == 2 and exponent % 4 == 2:
k = (exponent - 2) // 4
c = 1 + 2 ** (2*k + 1)
d = 2 ** (k + 1)
L = c + d
M = c - d
return k, c, d, L, M
Say, we have f(t) = v * t + A * sin(w * t). I call such functions "saw-like":
I want to solve saw(t) = C, that is, find a root of saw(t) - C (still "saw-like").
I tried writing down a ternary search for function abs(saw(t) - C) to find its minima. If we are lucky (or crafty), it would be the root. Unfortunately, my code does not always work: sometimes we get stuck in those places:
My code (python3):
def calculate(fun):
eps = 0.000000001
eps_l = 0.1
x = terns(fun, 0, 100000000000000)
t = terns(fun, 0, x)
cnt = 0
while fun(x) > eps:
t = x
x = terns(fun, 0, t)
if abs(t - x) < eps_l:
cnt += 1
# A sorry attempt pass some wrong value as a right one.
# Gets us out of an infinite loop at least.
if cnt == 10:
break
return t
def terns(f, l, r):
eps = 0.00000000001
while r - l > eps:
x_1 = l + (r - l) / 3
x_2 = r - (r - l) / 3
if f(x_1) < f(x_2):
r = x_2
else:
l = x_1
return (l + r) / 2
So, how is it done? Is using ternary search the right way?
My other idea was somehow sending the equation over to the net, passing it to Wolfram Alpha and fetching the answers. Yet, I don't how it's done, as I am not quite fluent at python.
How could this be done?
My idea is as follows:
import random
list=[]
while True:
A = random.uniform(0,3150) / 3150
B = random.uniform(0,2200) / 2200
C = random.uniform(0,1000) / 1000
D = random.uniform(0,2600) / 2600
E = random.uniform(0,2540) / 2540
F = random.uniform(0,1200) / 1200
G = random.uniform(0,1050) / 1050
if A+B+C+D+E+F+G == 0.965:
list[0] = A
list[1] = B
list[2] = C
list[3] = D
list[4] = E
list[5] = F
list[6] = G
print(list)
break
But even if I operate this code, it takes too long to get a list.
Should I
Firstly, I dont understand why you're using random.uniform(0, upperLim)/upperLimbecause it will always be a value between 0 and 1. But if that is a necessary part of your implementation then go ahead. Otherwise change it to random.uniform(0, 1) because that avoids an unnecessary multiplication and gives you greater precision too.
To make sure the sum of the random numbers is 0.965 here's what you can do to avoid looping and checking multiple times:
Firstly change the upper limit from the one you specified to something that returns max 0.965 i.e, random.uniform(0, 3150 * 0.965) / 3150
After this, generate the numbers according to the conditions that have already been met
maxLists = 100
currLists = 0
while True:
A = random.uniform(0, 0.965) # I'll use (0, 0.965) but you can replace it
B = random.uniform(0, 0.965 - A)
C = random.uniform(0, 0.965 - (A + B))
D = random.uniform(0, 0.965 - (A + B + C))
E = random.uniform(0, 0.965 - (A + B + C + D))
F = random.uniform(0, 0.965 - (A + B + C + D + E))
G = 0.965 - (A + B + C + D + E + F)
# populate them into a list
listOfNums = [A, B, C, D, E, F, G]
# get numbers that are zero because we want to prevent only the first few numbers adding
# upto 0.965 all the time
zeros = [i for i, e in enumerate(listOfNums) if e == 0]
nonZeros = [i for i, e in enumerate(listOfNums) if e != 0]
# do something with numbers here, maybe randomly take some part of the value from
# non zero indices and assign it to indices with zero value if you need the numbers
# to have some minimum value or if you have some other constraint
currLists += 1
print(listOfNums)
if currLists == maxLists: break
EDIT :
Here are some of the results I got after running it
[0.17790933642353207, 0.203575715409321, 0.17296325968456305, 0.12888905609400236, 0.07906382215736181, 0.19622480233464165, 0.006374007896577938]
[0.049602151767929197, 0.12732071710856213, 0.6719775449266687, 0.08616832676415115, 0.002068199017310945, 0.0015719942386102515, 0.026291066176767575]
[0.4216568638854053, 0.0841285730604016, 0.12581422942385648, 0.04125099314750179, 0.013789268384205427, 0.12463265303883869, 0.1537274190597907]
[0.39352655740635734, 0.08302194874949533, 0.05585858753600888, 0.14417023258593673, 0.17742466007873198, 0.042698164836977186, 0.06829984880649254]
[0.836553479500795, 0.019661470617368986, 0.06300565338226506, 0.021033910322500717, 0.0234921077113921, 0.0002043707861913963, 0.0010490076794867909]
[0.5334487166183782, 0.07743001493044013, 0.3431304879017562, 0.001616778025312949, 0.003948535326924425, 0.001755908717321748, 0.003669558479866386]
You can see the last few results are approaching zero, which is why you will either need to take some part of the previous values and add it to them or you can shuffle the numbers around randomly
Here is one way to do it, using a generator
import random
def solution(precision):
while True:
A = random.uniform(0,3150) / 3150
B = random.uniform(0,2200) / 2200
C = random.uniform(0,1000) / 1000
D = random.uniform(0,2600) / 2600
E = random.uniform(0,2540) / 2540
F = random.uniform(0,1200) / 1200
G = random.uniform(0,1050) / 1050
if abs(A+B+C+D+E+F+G - 0.965) <= precision:
yield [A, B, C, D, E, F, G]
and you get values satisfying the condition by calling
next(solution(0.001)) as many times as you need.
If you ask for a better precision, say 0.00001, it may take much longer to compute a solution.
Given some f and the differential equation x'(t) = f(x(t)), how do I compute x(n)(t) in terms of x(t)?
For example, given f(x(t)) = sin(x(t)),
I want to obtain x(3)(t) = (cos(x(t))2 − sin(x(t))2) sin(x(t)).
So far I've tried
>>> from sympy import diff, sin
>>> from sympy.abc import x, t
>>> diff(sin(x(t)), t, 2)
which gives me
-sin(x(t))*Derivative(x(t), t)**2 + cos(x(t))*Derivative(x(t), t, t)
but I'm not sure how to tell SymPy what Derivative(x(t), t) is and have it figure out Derivative(x(t), t, t), etc. automatically.
Answer:
Here's my final solution based on the answers I received below:
def diff(x_derivs_known, t, k, simplify=False):
try: n = len(x_derivs_known)
except TypeError: n = None
if n is None:
result = sympy.diff(x_derivs_known, t, k)
if simplify: result = result.simplify()
elif k < n:
result = x_derivs_known[k]
else:
i = n - 1
result = x_derivs_known[i]
while i < k:
result = result.diff(t)
j = len(x_derivs_known)
x0 = None
while j > 1:
j -= 1
result = result.subs(sympy.Derivative(x_derivs_known[0], t, j), x_derivs_known[j])
i += 1
if simplify: result = result.simplify()
return result
Example:
>>> diff((x(t), sympy.sin(x(t))), t, 3, True)
sin(x(t))*cos(2*x(t))
Here is one approach that returns a list of all derivatives up to n-th order
import sympy as sp
x = sp.Function('x')
t = sp.symbols('t')
f = lambda x: x**2 #sp.exp, sp.sin
n = 4 #3, 4, 5
deriv_list = [x(t), f(x(t))] # list of derivatives [x(t), x'(t), x''(t),...]
for i in range(1,n):
df_i = deriv_list[-1].diff(t).replace(sp.Derivative,lambda *args: f(x(t)))
deriv_list.append(df_i)
print(deriv_list)
[x(t), x(t)**2, 2*x(t)**3, 6*x(t)**4, 24*x(t)**5]
With f=sp.sin it returns
[x(t), sin(x(t)), sin(x(t))*cos(x(t)), -sin(x(t))**3 + sin(x(t))*cos(x(t))**2, -5*sin(x(t))**3*cos(x(t)) + sin(x(t))*cos(x(t))**3]
EDIT: A recursive function for the computation of the n-th derivative:
def der_xt(f, n):
if n==1:
return f(x(t))
else:
return der_xt(f,n-1).diff(t).replace(sp.Derivative,lambda *args: f(x(t)))
print(der_xt(sp.sin,3))
-sin(x(t))**3 + sin(x(t))*cos(x(t))**2
Declare f and use substitution:
>>> f = diff(x(t))
>>> diff(sin(x(t)), t, 2).subs(f, sin(x(t)))
-sin(x(t))**3 + cos(x(t))*Derivative(sin(x(t)), t)
I'm a new learner of python programming. Recently I'm trying to write a "tool" program of "dynamic programming" algorithm. However, the last part of my programe -- a while loop, failed to loop. the code is like
import numpy as np
beta, rho, B, M = 0.5, 0.9, 10, 5
S = range(B + M + 1) # State space = 0,...,B + M
Z = range(B + 1) # Shock space = 0,...,B
def U(c):
"Utility function."
return c**beta
def phi(z):
"Probability mass function, uniform distribution."
return 1.0 / len(Z) if 0 <= z <= B else 0
def Gamma(x):
"The correspondence of feasible actions."
return range(min(x, M) + 1)
def T(v):
"""An implementation of the Bellman operator.
Parameters: v is a sequence representing a function on S.
Returns: Tv, a list."""
Tv = []
for x in S:
# Compute the value of the objective function for each
# a in Gamma(x), and store the result in vals (n*m matrix)
vals = []
for a in Gamma(x):
y = U(x - a) + rho * sum(v[a + z]*phi(z) for z in Z)
# the place v comes into play, v is array for each state
vals.append(y)
# Store the maximum reward for this x in the list Tv
Tv.append(max(vals))
return Tv
# create initial value
def v_init():
v = []
for i in S:
val = []
for j in Gamma(i):
# deterministic
y = U(i-j)
val.append(y)
v.append(max(val))
return v
# Create an instance of value function
v = v_init()
# parameters
max_iter = 10000
tol = 0.0001
num_iter = 0
diff = 1.0
N = len(S)
# value iteration
value = np.empty([max_iter,N])
while (diff>=tol and num_iter<max_iter ):
v = T(v)
value[num_iter] = v
diff = np.abs(value[-1] - value[-2]).max()
num_iter = num_iter + 1
As you can see, the while loop at the bottom is used to iterate over "value function" and find the right answer. However, the while fails to loop, and just return num_iter=1. As for I know, the while loop "repeats a sequence of statements until some condition becomes false", clearly, this condition will not be satisfied until the diff converge to near 0
The major part of code works just fine, as far as I use the following for loop
value = np.empty([num_iter,N])
for x in range(num_iter):
v = T(v)
value[x] = v
diff = np.abs(value[-1] - value[-2]).max()
print(diff)
You define value as np.empty(...). That means that it is composed completely of zeros. The difference, therefore, between the last element and the second-to-last element will be zero. 0 is not >= 0.0001, so that expression will be False. Therefore, your loop breaks.