I have a very long symbolic expression in JupyterLab which I am trying to substitute values in. The expression is very long so I won't elaborate on what it is unless it is necessary, but I have a simplified symbolic expression which outputs (this is using SymPy). I am trying to use the .subs command as seen below, but this is not replacing any of the variables I have and rather just outputting the same symbolic notation. I have used .subs before, but in a very limited capacity so I am not sure if there is a type issue or something like that. All of these variables represent those in the symbolic notation.
replacements=[(t1,np.pi/2), (t1d,1), (t1dd,1), (l1,1), (l2,1), (m1,1), (m2,1), (m3,1), (g,-10)]
Lagrangian = Lagrangian.subs(replacements)
display(Lagrangian)
These variables are defined in the following way using the SymPy command symbols and then are manipulated to get the following expression. Not all of these symbols defined are in the final expression and are intermediary symbols.
l1, l2= sp.symbols('l_1, l_2')
y1, y2, y3, y1d, y2d, y3d = sp.symbols('y_1, y_2, y_3, ydot_1, ydot_2, ydot_3')
t1, t2, t1d, t2d= sp.symbols('theta_1, theta_1, thetadot_1, thetadot_2')
t1dd, t2dd = sp.symbols('thetaddot_1, thetaddot_2')
m1, m2, m3 = sp.symbols('m_1, m_2, m_3')
I1, I2 = sp.symbols('I_1, I_2')
g = sp.symbols('g')
When it comes to Lagrangian, it is just a manipulatioon of alll of these variables. I will show some of the following manipulations down below, but I do not think that the are not very necessary in causing the issue.
I1 = 1/3*m1*l1**2
I2 = 1/3*m2*l2**2
t2 = sp.acos(l1/l2*sp.sin(t1))
t2d = sp.diff(t2, t1) * t1d
y1 = 0.5*l1*sp.cos(t1)
y1d = sp.diff(y1,t1) * t1d
y2 = l1*sp.cos(t1) + 0.5*l2*sp.cos(t2)
y2d = 2*y1d - 0.5*l2*sp.sin(t2)*t2d
y3 = l1*sp.cos(t1) + l2*sp.cos(t2)
y3d = 2*y1d + 2*y2d
T = 0.5*m1*y1d**2 + 0.5*m2*y2d**2 + 0.5*m3*y3d**2 + 0.5*I1*t1d**2 + 0.5*I2*t2d**2
U = m1*g*y1 + m2*g*y2 + m3*g*y3
print('T=')
display(sp.simplify(T))
print('U=')
display(sp.simplify(U))
dTdTheta_dot = sp.diff(T,t1d)
dTdTheta = sp.diff(T,t1)
dUdTheta = sp.diff(U,t1)
#d_dt =
print('dT/dtheta_dot=')
display(sp.simplify(dTdTheta_dot))
print('dT/dTheta=')
display(sp.simplify(dTdTheta))
print('dU/dTheta=')
display(sp.simplify(dUdTheta))
A = (1/3)*l1**4*l2**2*m2*t1d**2*sp.sin(t1)*sp.cos(t1)**3
dA = (1/3)*l1**4*l2**4*m2*(2*t1d*t1dd*sp.sin(t1)*sp.cos(t1)**3+t1d**2*sp.cos(t1)*t1d*sp.cos(t1)**3+
t1d**2*sp.sin(t1)*3*sp.cos(t1)**2*(-sp.sin(t1)*t1d))
B = l1**2*((1/3)*l2**2*m2*l1**2*t1d*sp.sin(t1)**3*sp.cos(t1)-(1/3)*l2**4*m2*t1d*sp.cos(t1)*sp.cos(t1))
dB = l1**2*(((1/3)*l1**2*l2**2*m2*t1dd*sp.sin(t1)**3*sp.cos(t1) - (1/3)*l1**2*l2**2*m2*t1d*3*sp.sin(t1)**2*sp.cos(t1)*t1d*sp.cos(t1) +
(1/3)*l1**2/l2**2*m2*t1d*sp.sin(t1)**3*(-sp.sin(t1))*t1d) - ((1/3)*l1**4*m2*t1dd*sp.sin(t1)*sp.cos(t1)+
(1/3)*l2**4*m2*t1d*sp.cos(t1)*t1d*sp.cos(t1) + (1/3)*l2**4*m2*t1d*sp.sin(t1)*(-sp.sin(t1))*t1d))
C = l1**2*(l1**4*t1d*sp.sin(t1)**4 - 2*l1**2*l2**2*t1d*sp.sin(t1)**2 + l2**4*t1d)*((1/8)*m1*sp.sin(2*t1) + (3/8)*m2*sp.sin(2*t1) - (1/2)*m2)
dC = l1**2 * ((l1**4*(t1dd*sp.sin(t1)**4 + t1d*4*sp.sin(t1)**3*sp.cos(t1)*t1d) - 2*l1**2*l2**2*(t1dd*sp.sin(t1)**2 + t1d*2*sp.sin(t1)*sp.cos(t1)*t1d)+l2**4*t1dd) *
((1/8)*m1*sp.sin(2*t1) + (3/8)*m2*sp.sin(2*t1) - (1/2)*m2*sp.cos(2*t1)) + (l1**4*t1d*sp.sin(t1)**4 - 2*l1**2*l2**2*t1d*sp.sin(t1) + l2**4*t1d) *
((1/8)*m1*sp.cos(2*t1)*2*t1d + (3/8)*m2*sp.cos(2*t1)*2*t1d - (1/2)*m2*(-sp.sin(2*t1)*2*t1d)))
D = (4*m2*sp.sin(2*t1)-3*m3*sp.cos(2*t1)) * (l1**2*sp.sin(t1)**2-l2**2)**2
dD = (4*m2*sp.cos(2*t1)*2*t1d-3*m2*(-sp.sin(2*t1))*2*t1d)*((l1**2*sp.sin(t1)**2-l2**2)**2) + (4*m2*sp.sin(2*t1)-3*m3*sp.cos(2*t1))*(2*(l1**2*sp.sin(t1)-l2**2)*(2*l1**2*sp.sin(t1)*sp.cos(t1)*t1d))
E = (l1**2*sp.sin(t1)**2-l2**2)**-2
dE = -2*(l1**2*sp.sin(t1)-l2**2)**-3*(2*l1**2*sp.sin(t1)*sp.cos(t1)*t1d)
F = (dA+dB+dC+dD)*E + (A+B+C+D)*dE
display(sp.simplify(F))
Lagrangian = F - dTdTheta + dUdTheta
display(sp.simplify(Lagrangian))
Does anyone know why .subs doesn't work? Any help would be much appreciated. Thanks in advance!
I have written a code that I want to use to reduce measurement data. For this, I iterate through 30 sets of measurement data. In each iteration, I use fsolve to solve a set of three non-linear equations. This give me an array containing three values that are then further processed (in the example below lbda, alp, bta, dlt, q, N). I can print the results but would need to collect the data for all of the 30 cycles in an 30 by 6 array to do some statistics on (i.e. np.mean on each of the 6 variables).
I've tried the, for me, most obvious function(s) np.append, np.vstack, np.concatenates at the end of each iteration but this only gives me a 1 by 6 array containing only the last iteration step rather than the desired array containing all of the 30 iteration steps.
# loading data above
m1 = data_arr_blkcorr [:,4] / data_arr_blkcorr [:,2]
m2 = data_arr_blkcorr [:,5] / data_arr_blkcorr [:,2]
m3 = data_arr_blkcorr [:,7] / data_arr_blkcorr [:,2]
N=-1
while (N<29):
N = N+1
T1 = 79.744440299369400
T2 = 4.756431967877120
T3 = 195.146815878103000
T4 = 1.333609171398
T5 = 0.540566631391
T6 = 1
T7 = 1.731261585620
T_all = np.array([T4, T5, T6, T7, T1, T2, T3])
n1 = 0.598169735
n2 = 1.509919737
n3 = 0.600477235
n4 = 0.9364071191658
n5 = 0.5815716133216
n6 = 1
n7 = 1.0455228260642
n_all = np.array([n4, n5, n6, n7, n1, n2, n3])
I1 = 94.905838
I2 = 96.906018
I3 = 97.905405
I4 = 99.907473
I5 = 91.90681
I6 = 93.90509
I7 = 95.90468
# some definition of variables here
A11 = T1-n1
A12 = T2-n2
A13 = T3-n3
A21 = -n1*P1
A22 = -n2*P2
A23 = -n3*P3
A31 = m1[N] * P1
A32 = m2[N] * P2
A33 = m3[N] * P3
b11 = m1[N] - n1
b12 = m2[N] - n2
b13 = m3[N] - n3
# some definition of variables here
T = np.array ([T1, T2, T3])
n = np. array([n1, n2, n3])
m = np.array([m1[N], m2[N], m3[N]])
P = np.array([P1, P2, P3])
def F(x):
return x[0]*T + (1-x[0])*n*np.exp(-x[1]/(1-x[0])*P) - m*np.exp(-x[2]*P)
y = fsolve(F, guess)
lbda = y[0]
alp = y[1]/(1-y[0])
bta = y[2]
dlt = (np.exp(-alp*P2)-1)*1000
N_all = n_all * np.exp(-alp*P_all)
q = (1 + (1 - lbda) / lbda * np.sum(N_all) / np.sum(T_all))**(-1)
print (lbda, alp, bta, dlt, q, N)
Going through the posts I have also used this (after a suggestion provided by Koke Cacao):
data_sum = None
new_data = [lbda, alp, bta, dlt, q, N]
data_sum = np.append([data_sum], new_data) if data_sum is not None else new_data
print(data_sum)
But this yields a list of 30 isolated 1 by 6 arrays to which I do not have access to on the whole (i.e. to calculate np.means for individual values over all 30 iteration steps).
0.0209809690838 0.00142553246898 1.61537217874 -0.0443566490317 0.492710128581 26
(0.020980969083774538, 0.0014255324689812997, 1.6153721787428821, -0.044356649031684903, 0.4927101285811698, 26)
0.0209791772348 0.00272489389093 1.61486845411 -0.0847856651612 0.492691689834 27
(0.020979177234773643, 0.0027248938909269797, 1.6148684541135419, -0.084785665161235535, 0.49269168983354455, 27)
0.0209792771323 0.004884280445 1.61191395635 -0.151970341101 0.49269849879 28
(0.020979277132325381, 0.0048842804449965851, 1.6119139563515672, -0.15197034110059349, 0.4926984987899769, 28)
0.0209799414614 0.00256323393277 1.61366560195 -0.0797557810515 0.492700571038 29
(0.020979941461433328, 0.0025632339327746521, 1.6136656019498359, -0.079755781051460417, 0.49270057103806092, 29)
Also, it concatenates results over multiple runs (even after shutting down Python and restarting it) and I cannot clear this (sort of) memory.
try creating an empty list outside your while loop and then append the array.
solution = []
while n < 29:
#your code here
solution.append([lbda, alp, bta, dlt, q, N])
you should declare an empty list outside the while loop scope and then append to it on each Iteration:
result = []
while(N<29):
# calculate something
result.append(your_data)
print(result) # that will give you all the data that you got from each Iteration
I am working on solving and analyzing a system of differential equations in Python. First did I solve it with help of scipy.integrate dopri5 and scopes Odeint. Which worked out fine. Then I tried to solve the equations with use of the Euler's method. The equations and code is as followed,
dj = -mu*(J**3 - (C - C0)*J - F)
dc = J + C*F + a*J**2
df = J*F - C
T = 100
dt = 0.001
t = np.linspace(0, T, int(T/dt)+1)
j = np.zeros(len(t))
c = np.zeros(len(t))
f = np.zeros(len(t))
# Initial condition
j[0] = 0.1
c[0] = -0.5
f[0] = 0.1
a = 0.3025
C0 = 0.5
mu = 50
for i in range(len(t)):
j[i+1] = j[i] + (-mu * (j[i]**3 - (c[i] - C0)*j[i] - f[i]))*dt
c[i+1] = c[i] + (j[i] + c[i] * f[i] + (a * j[i])**2)*dt
f[i+1] = f[i] + (j[i] * f[i] - c[i])*dt
Is there any reason why the Euler's method should not work when both the other two are?
In the first iteration, i is 0, and your first line of the loop essentially is:
j[0] = j[-1] + (-mu * (j[-1]**3 - (c[-1] - C0)*j[-1] - f[-1]))*dt
j[-1] is the last element of j, just like c[-1] is the last element of c, etc. Initially they are all zeros, so j[0] becomes a 0, too, which overwrites the initial conditions. To fix this problem, change range(len(t)) to range(1,len(t)). (The model diverges after the first 9200 steps, anyway.)
As DYZ says, your calculation is incorrect on the first loop iteration because j[-1] is the last element of j, which you've initialised to zero.
However, your code wastes a lot of RAM. I assume you just want arrays containing T results, plus the initial values, rather than the results calculated on every step. The code below achieves that via a double for loop. We aren't really getting any benefit from Numpy in this code, so I don't bother importing it.
Note that Euler integration is not very accurate, and you generally need to use a much smaller step size than what's required by more sophisticated integration algorithms. As DYZ mentions, with your current step size the calculation diverges before the loop finishes.
Here's a modified version of your code using a smaller step size.
T = 100
dt = 0.00001
steps = int(T / dt)
substeps = int(steps / T)
# Recalculate `dt` to compensate for possible truncation
# in the `steps` and `substeps` calculations
dt = 1.0 / substeps
print('steps, substeps, dt:', steps, substeps, dt)
a = 0.3025
C0 = 0.5
mu = 50
#dj = -mu*(J**3 - (C - C0)*J - F)
#dc = J + C*F + a*J**2
#df = J*F - C
# Initial condition
j = 0.1
c = -0.5
f = 0.1
jlst, clst, flst = [j], [c], [f]
for i in range(T):
for _ in range(substeps):
j1 = j + (-mu * (j**3 - (c - C0)*j - f))*dt
c1 = c + (j + c * f + (a * j)**2)*dt
f1 = f + (j * f - c)*dt
j, c, f = j1, c1, f1
jlst.append(j)
clst.append(c)
flst.append(f)
def round_seq(seq, places=6):
return [round(u, places) for u in seq]
print('j:', round_seq(jlst), end='\n\n')
print('c:', round_seq(clst), end='\n\n')
print('f:', round_seq(flst), end='\n\n')
output
steps, substeps, dt: 10000000 100000 1e-05
j: [0.1, 0.585459, 1.26718, 3.557956, -1.311867, -0.647698, -0.133683, 0.395812, 0.964856, 3.009683, -2.025674, -1.047722, -0.48872, 0.044296, 0.581284, 1.245423, 14.725407, -1.715456, -0.907364, -0.372118, 0.167733, 0.705257, 1.511711, -3.588555, -1.476817, -0.778593, -0.253874, 0.289294, 0.837128, 1.985792, -2.652462, -1.28088, -0.657113, -0.132971, 0.409071, 0.983504, 3.229393, -2.1809, -1.113977, -0.539586, -0.009829, 0.528546, 1.156086, 8.23469, -1.838582, -0.967078, -0.423261, 0.113883, 0.650319, 1.381138, 12.045565, -1.575015, -0.833861, -0.305952, 0.23632, 0.778052, 1.734888, -2.925769, -1.362437, -0.709641, -0.186249, 0.356775, 0.917051, 2.507782, -2.367126, -1.184147, -0.590753, -0.063942, 0.476121, 1.07614, 5.085211, -1.976542, -1.029395, -0.474206, 0.059772, 0.596505, 1.273214, 17.083466, -1.682855, -0.890842, -0.357555, 0.182944, 0.721096, 1.554496, -3.331861, -1.450497, -0.763182, -0.239007, 0.30425, 0.85435, 2.076595, -2.584081, -1.258788, -0.642362, -0.117774, 0.423883, 1.003181, 3.521072, -2.132709, -1.094792, -0.525123]
c: [-0.5, -0.302644, 0.847742, 12.886781, 0.177404, -0.423405, -0.569541, -0.521669, -0.130084, 7.97828, -0.109606, -0.363033, -0.538874, -0.61005, -0.506872, 0.05076, 216.678959, -0.198445, -0.408569, -0.566869, -0.603713, -0.451729, 0.58959, 2.252504, -0.246645, -0.451, -0.588697, -0.587898, -0.375758, 2.152898, -0.087229, -0.295185, -0.49006, -0.603411, -0.562389, -0.263696, 8.901196, -0.132332, -0.342969, -0.525087, -0.609991, -0.526417, -0.077251, 67.082608, -0.177771, -0.389092, -0.555341, -0.607658, -0.47794, 0.293664, 147.817033, -0.225425, -0.432796, -0.579951, -0.595996, -0.412269, 1.235928, -0.037058, -0.273963, -0.473412, -0.597912, -0.574782, -0.318837, 4.581828, -0.113301, -0.3222, -0.51029, -0.608168, -0.543547, -0.172371, 24.718184, -0.157526, -0.369151, -0.542732, -0.609811, -0.500922, 0.09504, 291.915024, -0.204371, -0.414, -0.56993, -0.602265, -0.443622, 0.700005, 0.740665, -0.25268, -0.456048, -0.590933, -0.585265, -0.36427, 2.528225, -0.093699, -0.301181, -0.494644, -0.60469, -0.558516, -0.245806, 10.941068, -0.137816, -0.348805, -0.52912]
f: [0.1, 0.68085, 1.615135, 1.01107, -2.660947, -0.859348, -0.134789, 0.476782, 1.520241, 4.892319, -9.514924, -2.041217, -0.61413, 0.060247, 0.792463, 2.510586, 11.393914, -6.222736, -1.559576, -0.438133, 0.200729, 1.033274, 3.348756, -39.664752, -4.304545, -1.201378, -0.282146, 0.349631, 1.331995, 4.609547, -20.169056, -3.104072, -0.923759, -0.138225, 0.513633, 1.716341, 6.739864, -11.717002, -2.307614, -0.699883, 7.4e-05, 0.700823, 2.22957, 11.017447, -7.434886, -1.751919, -0.512171, 0.138566, 0.922012, 2.9434, -30.549886, -5.028825, -1.346261, -0.348547, 0.282981, 1.19254, 3.987366, -26.554232, -3.566328, -1.0374, -0.200198, 0.439487, 1.535198, 5.645421, -14.674838, -2.619369, -0.792589, -0.060175, 0.615387, 1.985246, 8.779969, -8.991742, -1.972575, -0.590788, 0.077534, 0.820118, 2.599728, 8.879606, -5.928246, -1.509453, -0.417854, 0.218635, 1.066761, 3.477148, -36.053938, -4.124934, -1.163178, -0.263755, 0.369033, 1.37438, 4.811848, -18.741635, -2.987496, -0.893457, -0.120864, 0.535433, 1.771958, 7.117055, -11.027021, -2.227847, -0.674889]
That takes about 75 seconds on my old 2GHz machine.
Using dt = 0.000005 (which takes almost 2 minutes on this machine) the final values of j, c, and f are -0.524774, -0.529217, -0.674293, respectively, so it looks like we're beginning to get convergence.
Thanks to LutzL for pointing out that dt may need adjusting because of the rounding in the steps and substeps calculations.