I am trying to solve a system of 16 nonlinear equations that has 16 unknowns using lsqnonlin.
my variables are all depend on other equations (exp: SegmaD is unknown and defined as (SegmaD= EpR2Teta) then (Teta= fcr-Epcr/2*FT) then Epcr=EpA/TX and as you can see EPA has an if statement so I defined all the variables as symbolic, but I am getting errors that you can't use if statement with symbolic (I am a beginner in Matlab) so I want to construct my 16 equations by substituting other ones that has the unknowns to solve by lsqnonlin, how can I do that symbolically and then solve for a given value? what is the best way to approach this? I have attached a part of my code to give a brief understanding of what is going on. Thanks
code:
syms Tx EpDs EpR EpA EpL K1 SegmaR Teta SegmaD FT EpT q AlphaD GamaLT
SegmaR(i) = Fcr*(EpR(i)/Epcr);
Teta(i) = 0.9/(sqrt(1+600*EpR(i))); % Teta is the Softening Coefficient equation 17
% K1 equation 16
if (EpA(i) < EpDs(i))
K1(i)= ((EpDs(i)/Ep0)*(1-(EpDs(i)/3*Ep0))-((EpA(i))^2)/(EpDs(i)*Ep0))*(1-((EpA(i)/3*Ep0)))*(EpDs(i)/(EpDs(i)-EpA(i)));
elseif (EpA(i)==EpDs(i))
K1(i)= ((2*EpDs(i)*Ep0)-EpDs(i)^2/Ep0^2); %K1 is a Dimensionless Parameter
end
SegmaD(i) = K1(i)*Teta(i)*fck; % SegmaD is the evolution of concrete compressive stress equation 15
EpT(i) = EpR(i)+EpD(i)-EpL(i); %equation 14
FT(i) = (Es*EpT(i))*(0.002+((1-0.002)/(1+((1-0.002)*(EpT(i)/EpSy))^4)^0.25)); % Equation 21
First note that you only defined 14 symbolic variables and not 16 with syms. You should also check your parentheses again! Some are extra and some are missing. It is also not clear what you want to do in the end with these expressions. But anyways, one important thing is that a symbolic variable and a symbolic function or a variable and a function in general are not the same things. What I see is that EpR in your code is not a variable, but a function of t (I changed your i with t because t makes more sense for me such as time for example whereas i to me is usually an integer counter ^_^). To see how to define a symbolic function in Matlab see its help page https://uk.mathworks.com/help/symbolic/create-symbolic-functions.html or this one https://uk.mathworks.com/help/symbolic/symfun.html. One more thing is that when the equation of your function changes depending on some conditions, then in fact you have a piecewise function. Here is the help page for piecewise functions in Matlab https://uk.mathworks.com/help/symbolic/piecewise.html, and for definition of piecewise functions in general you can look at its Wikipedia page https://en.wikipedia.org/wiki/Piecewise. Here is how I rewrote your code. You may wonder why I have different lines of syms, it is just because I saw many symbols in your code that are not in your syms-line, so I looked at your code and add one syms for each symbol I encountered. You can make them in one line yourself. Now if you run this, you do not see any error message.
syms EpR( t )
syms Fcr
syms Epcr
syms SegmaR( t )
SegmaR( t ) = Fcr * ( EpR( t ) / Epcr );
syms Teta( t )
Teta( t ) = 0.9 / sqrt( 1 + 600 * EpR( t ) );
syms EpA( t )
syms EpDs( t )
syms Ep0
syms K1( t )
K1( t ) = piecewise( EpA( t ) < EpDs( t ), (EpDs( t ) / Ep0 ) * (1 - (EpDs( t )/ (3 * Ep0 ) )) - ((EpA( t ) ^ 2 ) / (EpDs( t ) * Ep0)) * (EpDs( t ) / (EpDs( t ) - EpA( t ))), EpA( t ) == EpDs( t ), 2 * EpDs( t ) * Ep0 - EpDs( t ) ^ 2 / Ep0 ^ 2 );
syms fck
syms SegmaD( t )
SegmaD( t ) = K1( t ) * Teta( t ) * fck;
syms EpR( t )
syms EpD( t )
syms EpL( t )
syms EpT( t )
EpT( t ) = EpR( t ) + EpD( t ) - EpL( t );
syms Es
syms EpSy
syms FT( t )
FT( t ) = Es * EpT( t ) * ( 0.002 + (1 - 0.002) / (1 + ((1 - 0.002) * (EpT( t ) / EpSy)) ^ 4) ^ 0.25);
% doing something to be sure symbolic functions are defined fine.
disp( diff( FT, t ));
Your "part of code" does not include any system of equations. You can edit your question and include it.
Related
I am trying to solve the following system of 2 delay differential equations using dde23 in MATLAB. The solver seems to work for equation 2, but for the first equation it chooses the trivial solution v(1) = 0 (as shown in attached plot). Literature on dde23 does not indicate that it has a feature to force the solution to be nonzero / positive (as in ode solvers); is there a way I can force dde23 to search for nontrivial, >0 solutions? Or some workaround for this issue? Any suggestions would be much appreciated. Thank you!
Equations:
v(1) = (Aval - f) * v(1) - b * v(1) * 2; %S eqn
v(2) = h * b * ylagS(1) * ylagV(2) - b * v(1) * v(2) - m * v(2); %V eqn
Defined constants:
Aval = 1.; %Various constants defined here
f = 10^-5;
b = 10^-7;
h = 1.5;
m = 0.0003;
This example solves a DDE on the interval [0, 5] with lags 1 and 0.2. The function ddex1de computes the delay differential equations, and ddex1hist computes the history for t <= 0.
Note
The file, ddex1.m, contains the complete code for this example. To see the code in an editor, type edit ddex1 at the command line. To run it, type ddex1 at the command line.
sol = dde23(#ddex1de,[1, 0.2],#ddex1hist,[0, 5]);
This code evaluates the solution at 100 equally spaced points in the interval [0,5], then plots the result.
tint = linspace(0,5);
yint = deval(sol,tint);
plot(tint,yint)
I am given a set of points (p1,q1) (p2,q2) ... (p20,q20) which satisfy the function q = 1/(ap + b)^2 except that one of these does not satisfy the given relation. The values of a and b are not given to me. All I have with me is two inputs p and q as arrays. I need to find the index of the point which does not satisfy the given relation.
The way I proceeded to solve is to find the values of a and b using the first two pairs (p1,q1) and (p2,q2) and check if the remaining points satisfy the function for the solved values of a and b. The results will be stored in a logical matrix. I wish to make use of the logical matrix to pick out the odd pair, but unable to proceed further.
Specifically, the challenge is to make use of vectorization in MATLAB to find the odd point, instead of resorting to for-loops. I think that I will have to first search for the only logical zero in any of the row. In that case, the column index of that zero will fetch me the odd point. But, if there are more than one zeros in all 4 rows, then the odd point is either of the first two pairs. I need help in translating this to efficient code in MATLAB.
Please note that vectors p and q have been named as x and y in the below code.
function [res, sol] = findThePair(x, y)
N = length(x);
syms a b
vars = [a,b];
eqns = [y(1) - 1/(a*x(1) + b)^2 == 0; y(2) - 1/(a*x(2) + b)^2];
[solA, solB] = solve(eqns,vars);
sol = [double(solA) double(solB)]; %solution of a & b (total 4 possibilites)
xTest = x(3:end); % performing check on remaining points
yTest = y(3:end);
res = zeros(4, N-2); % logical matrix to store the results of equality check
for i = 1:4
A = sol(i,1); B = sol(i, 2);
res(i, :) = [yTest == 1./(A*xTest + B).^2]; % perform equality check on remaining points
end
Let's do some maths up front, to avoid needing loops or vectorisation. At most this leaves us with half a dozen function evaluations, and we only need 5 points.
q = 1 / (a*p + b)^2
% ->
sqrt(q) * ( a*p + b ) = 1
% ->
a = ( 1 - b*sqrt(q) ) / ( p * sqrt(q) )
% Sub in some points (1 and 2) ->
a1 = ( 1 - b*sqrt(q1) ) / ( p1 * sqrt(q1) )
a2 = ( 1 - b*sqrt(q2) ) / ( p2 * sqrt(q2) )
% a1 and a2 should be the same ->
( 1 - b*sqrt(q1) ) * ( p2 * sqrt(q2) ) = ( 1 - b*sqrt(q2) ) * ( p1 * sqrt(q1) )
% Rearrange ->
b = ( p2*sqrt(q2) - p1*sqrt(q1) ) / ( (p2-p1)*sqrt(q1)*sqrt(q2) )
We have two unknowns, a and b. All we need are two points to create simultaneous equations. I'll use the following logic
Choose (pm, qm) and (pn, qn) with any m ~= n.
Calculate a and b using the above equation.
test whether (pr, qr) fits with the calculated a and b.
If it fits, we know all three of these must be on the curve, and we have a and b.
If it doesn't fit, we know either point m, n, or r is the outlier. Return to step (1) with two other points, the calculated a and b must be correct, as we've not fitted to the outlier.
Here is some code to implement this:
% Random coeffs, keep things unknown
a = rand*10;
b = rand*10;
% Set up our data
p = 1:20;
q = 1 ./ (a*p + b).^2;
% Create an outlier
q( 3 ) = q( 3 ) + 1;
% Steps as described
% 1.
p1 = p(1); p2 = p(2);
q1 = q(1); q2 = q(2);
% 2.
bGuess = ( p2*sqrt(q2) - p1*sqrt(q1) ) / ( (p2-p1)*sqrt(q1)*sqrt(q2) );
aGuess = ( 1 - bGuess*sqrt(q1) ) / ( p1 * sqrt(q1) );
% 3.
p3 = p(3);
q3Guess = 1 / ( aGuess*p3 + bGuess )^2;
tol = 1e-7; % Use tolerance rather than == comparison to avoid float issues
if abs( q3Guess - q(3) ) < tol
% success
aFit = aGuess;
bFit = bGuess;
else
% p1, p2 or p3 is an outlier! Repeat using other points
% If there's known to be only one outlier, this should give the result
p1 = p(4); p2 = p(5);
q1 = q(4); q2 = q(5);
bFit = ( p2*sqrt(q2) - p1*sqrt(q1) ) / ( (p2-p1)*sqrt(q1)*sqrt(q2) );
aFit = ( 1 - bFit*sqrt(q1) ) / ( p1 * sqrt(q1) );
end
% Validate
fprintf( 'a is valid: %d, b is valid: %d\n', abs(a-aFit)<tol, abs(b-bFit)<tol )
I don't really understand how you were trying to solve this and what do syms (i.e. symbolic variables) have to do with this, so I'll show you how I would solve this problem.
Since we're essentially looking for an outlier, we might as well convert the problem to something that's easier to work with. For this reason, instead of using q as-is, I'm going to invert it: this way, we'd be dealing with an equation of a parabola - which is easy.
Next, knowing that our points should lie on a parabola, we can fit the equation of the parabola (or equivalently - find the coefficients of the polynomial that describes the relation of the input to the output). The polynomial is a^2*x^2+2*a*b*x+b^2, and so the coefficients are {a^2, 2*a*b, b^2}.
Since the majority of the points (19 out of 20) lie on the same parabola, the outlier will always have a larger error, which would make it stand out, no matter how close it is to the parabola (within the limitations of machine precision) - you can see an extreme example of this in the code below.
Fitting of a parabola is performed using polynomial interpolation (see also: Vandermonde matrix).
function I = q55241683()
%% Generate the ground truth:
TRUE_A = 2.3;
TRUE_B = -pi;
IDX_BAD = 5;
p = 1:0.04:1.76;
q = (TRUE_A * p + TRUE_B).^-2;
q(IDX_BAD) = (1-1E-10)*q(IDX_BAD); % notice just how close this is to being valid
%% Visualize dataset:
% figure(); plot(p,q.^-1);
%% Solve
I = findThePair(p, q.^-1);
%% Test
if IDX_BAD == I
disp('Great success!');
else
disp('Complete failure!');
end
end
function I = findThePair(x,y)
% Fit a parabola to {x vs. y^-1}
P = x(:).^(2:-1:0)\y(:); %alternatively: P = polyfit(x,y.^-1,2)
% Estimate {a,b} (or {-a,-b})
est_A = sqrt(P(1));
est_B = P(2)/(2*est_A);
% Compute the distances of the points from the fit (residuals), find the biggest:
[~,I] = max( abs(y - (est_A*x + est_B).^2) );
end
2nd ODE to solve in MATLAB:
( (a + f(t))·d²x/dt² + (b/2 + k(t))·dx/dt ) · dx/dt - g(t) = 0
Boundary condition:
dx/dt(0) = v0
where
t is the time,
x is the position
dx/dt is the velocity
d2x/dt2 is the acceleration
a, b, v0 are constants
f(t), k(t) and h(t) are KNOWN functions dependent on t
(I do not write them because they are quite big)
As an example, using symbolic variables:
syms t y
%% --- Initial conditions ---
phi = 12.5e-3;
v0 = 300;
e = 3e-3;
ro = 1580;
E = 43e9;
e_r = 0.01466;
B = 0.28e-3;
%% --- Intermediate calculations ---
v_T = sqrt(((1 + e_r) * 620e6) /E) - sqrt(E/ro) * e_r;
R_T = v_T * t;
m_acc = pi * e * ro *(R_T^2);
v_L = sqrt (E/ro);
R_L = v_L * t;
z = 2 * R_L;
E_4 = B * ((e_r^2)* B * (0.9^(z/B)-1)) /(log(0.9));
E_1 = E * e * pi * e_r^2 * (-phi* (phi - 2*v_T*t)) /16;
E_2 = pi * R_T^2 * 10e9;
E_3 = pi * R_T^2 * 1e6 * e;
%% Resolution of the problem
g_t = -diff(E_1 + E_2 + E_3, t);
f(t,y)=(g_t - (pi*v_T*e*ro/2 + E_4) * y^2 /(y* (8.33e-3 + m_acc))];
fun=matlabFunction(f);
[T,Y]=ode45(fun,[0 1], v0]);
How can I rewrite this to get x as y=dx/dt? I'm new to Matlab and any help is very welcome !
First, you chould use subs to evaluate a symbolic function. Another approach is to use matlabFunction to convert all symbolic expressions to anonymous functions, as suggested by Horchler.
Second, you're integrating the ODE as if it is 1st order in dx/dt. If you're interested in x(t) as well as dx/dt(t), then you'll have to modify the function like so:
fun = #(t,y) [y(2);
( subs(g) - (b/2 + subs(k))*y(2)*y(2) ) / ( y(2) * (a + subs(f))) ];
and of course, provide an initial value for x0 = x(0) as well as v0 = dx/dt(0).
Third, the absolute value of the parameters is hardly ever a real concern. IEEE754 double-precision floating point format can effortlessly represent numbers between 2.225073858507201e-308 and 1.797693134862316e+308 (realmin and realmax, respectively). So for the coefficients you gave (O(1014)), this is absolutely not a problem. You might lose a few digits of precision if you don't take precautions (rescale to [-1 +1], reformulate the problem in different units, ...), but the relative error due to this is more than likely to be tiny and insignificant compared to the algorithmic error made by ode45.
<RANDOM_OPINIONATED_RANT>
Fourth, WHY do you use symbolic math for this purpose?! You are doing a numerical integration, meaning, there is no analytic solution anyway. Why bother with symbolics then? Doing the integration with symbolics (through vpa even) is going to be dozens, hundreds, yes, often even thousands of times slower than keeping (or re-implementing) everything numerical (which some would argue is already slow in MATLAB compared to a bare-metal approach).
Yes, of course, for this specific, individual, isolated use case it may not matter much, but for the future I'd strongly advise you to learn to:
use symbolics for derivations, proving theorems, simplifying expressions, ...
use numerics to implement any algorithm or function from which actual numbers are expected.
In other words, symbolics for drafting, numerics for crunching. And exactly zero symbolics should appear in any good implementation of any algorithm.
Although it's possible to mix them to some extent, that does not mean it is a good idea to do so. In fact, that's almost never. And the few isolated cases where it is the only viable option are not a vindication of the approach.
They are rare, isolated cases after all, far from the abundant norm.
For me it bears resemblance with the evil eval, with similar reasons for why it Should. Be. Avoided.
</RANDOM_OPINIONATED_RANT>
With the full code, it's easy to come up with a complete solution:
% Initial conditions
phi = 12.5e-3;
v0 = 300;
x0 = 0; % (my assumption)
e = 3e-3;
ro = 1580;
E = 43e9;
e_r = 0.01466;
B = 0.28e-3;
% Intermediate calculations
v_T = sqrt(((1 + e_r) * 620e6) /E) - sqrt(E/ro) * e_r;
R_T = #(t) v_T * t;
m_acc = #(t) pi * e * ro *(R_T(t)^2);
v_L = sqrt (E/ro);
R_L = #(t) v_L * t;
z = #(t) 2 * R_L(t);
E_4 = #(t) B * ((e_r^2)* B * (0.9^(z(t)/B)-1)) /(log(0.9));
% UNUSED
%{
E_1 = #(t) -phi * E * e * pi * e_r^2 * (phi - 2*v_T*t) /16;
E_2 = #(t) pi * R_T(t)^2 * 10e9;
E_3 = #(t) pi * R_T(t)^2 * 1e6 * e;
%}
% Resolution of the problem
g_t = #(t) -( phi * E * e * pi * e_r^2 * v_T / 8 + ... % dE_1/dt
pi * 10e9 * 2 * R_T(t) * v_T + ... % dE_2/dt
pi * 1e6 * e * 2 * R_T(t) * v_T ); % dE_3/dt
% The derivative of Z = [x(t); x'(t)] equals Z' = [x'(t); x''(t)]
f = #(t,y)[y(2);
(g_t(t) - (0.5*pi*v_T*e*ro + E_4(t)) * y(2)^2) /(y(2) * (8.33e-3 + m_acc(t)))];
% Which is readily integrated
[T,Y] = ode45(f, [0 1], [x0 v0]);
% Plot solutions
figure(1)
plot(T, Y(:,1))
xlabel('t [s]'), ylabel('position [m]')
figure(2)
plot(T, Y(:,2))
xlabel('t [s]'), ylabel('velocity [m/s]')
Results:
Note that I've not used symbolics anywhere, except to double-check my hand-derived derivatives.
I created an Octave script for training a neural network with 1 hidden layer using backpropagation but it can not seem to fit an XOR function.
x Input 4x2 matrix [0 0; 0 1; 1 0; 1 1]
y Output 4x1 matrix [0; 1; 1; 0]
theta Hidden / output layer weights
z Weighted sums
a Activation function applied to weighted sums
m Sample count (4 here)
My weights are initialized as follows
epsilon_init = 0.12;
theta1 = rand(hiddenCount, inputCount + 1) * 2 * epsilon_init * epsilon_init;
theta2 = rand(outputCount, hiddenCount + 1) * 2 * epsilon_init * epsilon_init;
Feed forward
a1 = x;
a1_with_bias = [ones(m, 1) a1];
z2 = a1_with_bias * theta1';
a2 = sigmoid(z2);
a2_with_bias = [ones(size(a2, 1), 1) a2];
z3 = a2_with_bias * theta2';
a3 = sigmoid(z3);
Then I compute the logistic cost function
j = -sum((y .* log(a3) + (1 - y) .* log(1 - a3))(:)) / m;
Back propagation
delta2 = (a3 - y);
gradient2 = delta2' * a2_with_bias / m;
delta1 = (delta2 * theta2(:, 2:end)) .* sigmoidGradient(z2);
gradient1 = delta1' * a1_with_bias / m;
The gradients were verified to be correct using gradient checking.
I then use these gradients to find the optimal values for theta using gradient descent, though using Octave's fminunc function yields the same results. The cost function converges to ln(2) (or 0.5 for a squared errors cost function) because the network outputs 0.5 for all four inputs no matter how many hidden units I use.
Does anyone know where my mistake is?
Start with a larger range when initialising weights, including negative values. It is difficult for your code to "cross-over" between positive and negative weights, and you probably meant to put * 2 * epsilon_init - epsilon_init; when instead you put * 2 * epsilon_init * epsilon_init;. Fixing that may well fix your code.
As a rule of thumb, I would do something like this:
theta1 = ( 0.5 * sqrt ( 6 / ( inputCount + hiddenCount) ) *
randn( hiddenCount, inputCount + 1 ) );
theta2 = ( 0.5 * sqrt ( 6 / ( hiddenCount + outputCount ) ) *
randn( outputCount, hiddenCount + 1 ) );
The multiplier is just some advice I picked up on a course, I think that it is backed by a research paper that compared a few different approaches.
In addition, you may need a lot of iterations to learn XOR if you run basic gradient descent. I suggest running for at least 10000 before declaring that learning isn't working. The fminunc function should do better than that.
I ran your code with 2 hidden neurons, basic gradient descent and the above initialisations, and it learned XOR correctly. I also tried adding momentum terms, and the learning was faster and more reliable, so I suggest you take a look at that next.
You need at least 3 neurons in the hidden layer and correct the initialization as the first answer suggest.
If the sigmoidGradient(z2) means a2.*(1-a2) all the rest of the code seems ok to me.
Best reggards,
The differential equation is:
k*r=sqrt( (r`)^2 + r^2 )
The value of k is 2. How can I realize the function and solve it with ode45?
This is pretty straightforward. A few important things:
You need to express your differential equation in the format that ODE45 expects, which is dy/dt = f(t,y). That means that for your function, rather than k*r=sqrt( (drdt)^2 + r^2 ), you need to consider this as drdt = sqrt( (k*r)^2 - r^2 ) (assumming that I did my algebra correctly).
The function needs to be vectorizable. For this problem, that pretty much means that instead of ^, use .^, and instead of *, use .*.
Then we can use basic anonymous function syntax to setup the function to be solved:
k = 2;
fn_drdt = #(t,r) sqrt( (k.*r).^2 - (r.^2) );
Use ODE45 to solve it
tStart = 0;
tEnd = 10;
r_init = -5;
[t, r] = ode45(fn_drdt, [tStart tEnd], r_init);
And then make a basic plot
plot(t,r,'.');
And add a title
title(sprintf('Solution to %s with k=%d ,r_0=%d', func2str(fn_drdt), k, r_init), 'fontname','courier')