Warning: Possibly spurious solutions. [solvelib::checkSolutions] - matlab

I am trying to solve four algebraic equations in a for loop. It is giving a warning 'Possibly spurious solutions'. Could you please help me to figure out how to remove it. Code is attached herewith.
a=[1.78E-05 3.39E-04 0.0104 -0.05791 -16.36];
for i=1:R/l0
syms x y l r
[sol_l,sol_r,sol_x,sol_y] = solve(l == (sqrt((x-x0)^2+(y-y0)^2)), r == abs((x+x0)/2),...
poly2sym(a) == y, l*r*t == l0*r0*t0,x,y,l,r, 'Real', true);
for j=1:length(sol_x)
if (sol_x(j)<0)&&(sol_x(j)>x0)
if (sol_y(j)<0)&&(sol_y(j)<y0)
x_req(1,i) = sol_x(j);
y_req(1,i) = sol_y(j);
end
end
end
x0 = x_req(1,i);
y0 = y_req(1,i);
r0 = R-l0*(2*i-1)/2;
end

If you change your first equation to this, the warning no longer crops up:
l^2 == (x-x0)^2+(y-y0)^2
I'm not sure that you actually have spurious values though. The it's possible that the square root gave solvelib::checkSolutions trouble.
You may have thought that you had spurious values when you checked because you weren't outputting the variables correctly. You specify that solve solve for x, y, l, r (in that order), but then you name the output variables as sol_l, sol_r, sol_x, sol_y (different order). You must use the same order as `solve cannot guess bases on the names of your variables.
Your code:
R=30;
x0=-R;
y0=0;
l0=R/100;
t0=1.2;
t=0.7071;
r0=R-l0/2;
a=[1.78E-05 3.39E-04 0.0104 -0.05791 -16.36];
[sol_x,sol_y,sol_l,sol_r] = solve(l^2 == (x-x0)^2+(y-y0)^2, ...
r == abs((x+x0)/2), ...
poly2sym(a) == y, ...
l*r*t == l0*r0*t0, ...
x,y,l,r, 'Real', true)
% Check
sol_l2.^2 - (sol_x2-x0).^2+(sol_y2-y0).^2
sol_r - abs((sol_x+x0)/2)
[subs(poly2sym(a),x,sol_x(1));subs(poly2sym(a),x,sol_x(2));...
subs(poly2sym(a),x,sol_x(3));subs(poly2sym(a),x,sol_x(4))]-sol_y;
sol_l2.*sol_r2*t - l0*r0*t0
The check returns small values close zero.

Related

How to solve a matlab fit?

So I want to solve a plot fit for several points, but the problem, that I am facing right now is, that my fit object fit_eq is a char but solve needs a sym. I searched everywhere and couldn't find a solution how to fix this. Here is my code, I cut unimportant parts, and some variables are german words, so don't get confused. gesamt is a 60x20 matrix, where every odd column is the same (it's made out of 10 matrices which are an outcome of a meassurement).
anzahlproben = 10;
for i = 1:2:anzahlproben*2
probe = gesamt(:,i:i+1);
[row c]=find(probe==0);
row(1:2,:)=[];
for j=row
probe(j,:)=[];
end
N22_{(i+1)/2} = probe;
end
for i = 1:1:anzahlproben
x = N22_{i}(1:1:size(N22_{i},1),1);
y = N22_{i}(1:1:size(N22_{i},1),2);
ft = fittype('poly9');
fitobject_{i}=fit(x,y,ft);
end
cvalues = coeffvalues(fitobject_{1});
cnames = coeffnames(fitobject_{1});
fit_eq = formula(fitobject_{1});
for ii=1:1:numel(cvalues)
cname = cnames{ii};
cvalue = num2str(cvalues(ii));
fit_eq = strrep(fit_eq, cname , cvalue);
end
y=1;
syms x
erg = (solve(fit_eq == y,x))
I got the last part from here and gives an equation in a char.
Matlab gives the output:
erg =
Empty sym: 0-by-1
Which can't be right. Any ideas?
As mentioned in the first line of the doc:
Support for character vector or string inputs has been removed.
Instead, use syms to declare variables and replace inputs such as
solve('2*x == 1','x') with solve(2*x == 1,x).
So eqn should be of class sym not a string!
Try:
erg = solve(str2sym(fit_eq) == y,x)
If it still don't work either your equation is wrong or you've not declared the symbolic variables involved in your equation.

An error without actually explaining what's wrong

Ok, so I've defined the function MetBisectiei which has the following code:
function [xaprox] = MetBisectiei(Fun,a,b,eps)
Fa = Fun(a);
Fb = Fun(b);
if Fa*Fb>0
xaprox = ('Error: The function has the same sign at points a and b.');
else
N=ceil((log10(b-a)-log10(eps))/log10(2));
for i = 1:n
xaprox = (a+b)/2;
Fxaprox=Fun(xaprox);
if(Fxaprox == 0)
break
end
if Fa*Fxaprox<0
b=Fxaprox;
else
a=xaprox;
Fa=Fxaprox;
end
end
end
And when I try to actually use the function to find the solution of an equation, I get the following error, which doesn't actually explain what's wrong:
Error in tema2_2 (line 8)
xaprox = MetBisectiei(f,0,1,eps);
The code to find the solution of the equation is this one:
syms x
f = x^3-7*x^2+14*x-6;
f = matlabFunction(f);
x = 0:4;
y = f(x);
plot(x,y);
eps = 10^(-5);
xaprox = MetBisectiei(f,0,1,eps);
I see few mistakes here. First you should terminate
function [xaprox] = MetBisectiei(Fun,a,b,eps)
with end, the one visible in your example just close if statement. The second problem is that n is not defined, probably you miss that matlab is case-sensitive, and N is not equal to n. So you should:
n=ceil((log10(b-a)-log10(eps))/log10(2));
If you fix this two things - your codes finish without any errors, (xaprox = 0.5210) tested on Matlab R2017b.

Why is this for loop giving me an error?

So I am trying to go through a for loop that will increment .1 every time and will do this until the another variable h is less than or equal to zero. Then I am suppose to graph this h variable along another variable x. The code that I wrote looks like this:
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
h(t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
The Error that I keep getting when running this code says "Attempted to access h(0); index must be a positive integer or logical." I don't understand what exactly is going on in order for this to happen. So my question is why is this happening and is there a way I can solve it, Thank you in advance.
You're using t as your loop variable as well as your indexing variable. This doesn't work, because you'll try to access h(0), h(0.1), h(0.2), etc, which doesn't make sense. As the error says, you can only access variables using integers. You could replace your code with the following:
t = 0:0.1:12;
for i = 1:length(t)
% use t(i) instead of t now
end
I will also point out that you don't need to use a for loop to do this. MATLAB is optimised for acting on matrices (and vectors), and will in general run faster on vectorised functions rather than for loops. For instance, your equation for h could be replaced with the following:
O = 20;
v = 200;
g = 32.2;
t = 0:0.1:12;
h = v * t * sin(O) - 0.5 * g * t.^2;
The only difference is that you have to use the element-wise square (.^2) rather than the normal square (^2). This means that MATLAB will square each element of the vector t, rather than multiplying the vector t by itself.
In short:
As the error says, t needs to be an integer or logical.
But your t is t=0:0.1:12, therefore a decimal value.
O = 20;
v = 200;
g = 32.2;
for t = 0:.1:12
% Calculate the height
idx_t = 1:numel(t);
h(idx_t) = (v)*(t)*(sin(O))-(1/2)*(g)*(t^2);
% Calculate the horizontal location
x(idx_t) = (v)*(t)*cos(O);
if t > 0 && h <= 0
break
end
end
Look this question's answer for more options: Subscript indices must either be real positive integers or logical error

Calculating Errors of the Trapezoidal Rule in MATLAB

I'm trying to calculate how the errors depend on the step, h, for the trapezoidal rule. The errors should get smaller with a smaller value of h, but for me this doesn't happen. This is my code:
Iref is a reference value calculated and verified with Simpson's method and the MATLAB function quad, respectively
for h = 0.01:0.1:1
x = a:h:b;
v = y(x);
Itrap = (sum(v)-v(1)/2-v(end)/2)*h;
Error = abs(Itrap-Iref)
end
I think there's something wrong with the way I'm using h, because the trapezoidal rule works for known integrals. I would be really happy if someone could help me with this, because I can't understand why the errors are "jumping around" the way the do.
I wonder if maybe part of the problem is that not all intervals - for each step size h - have the same a and b just because of the way that x is constructed. Try the following with the additional fprintf statement:
for h = 0.01:0.1:1
x = a:h:b;
fprintf('a=%f b=%f\n',x(1),x(end));
v = y(x);
Itrap = (sum(v)-v(1)/2-v(end)/2)*h;
Error = abs(Itrap-Iref);
end
Depending upon your a and b (I chose a=0 and b=5) all the a values were identical (as expected) but the b varied from 4.55 to 5.0.
I think that you always want to keep the interval [a,b] the same for each step size that you choose in order to get a better comparison between each iteration. So rather than iterating over the step size, you could instead iterate over the n, the number of equally spaced sub-intervals within [a,b].
Rather than
for h = 0.01:0.1:1
x = a:h:b;
you could do something more like
% iterate over each value of n, chosen so that the step size
% is similar to what you had before
for n = [501 46 24 17 13 10 9 8 7 6]
% create an equally spaced vector of n numbers between a and b
x = linspace(a,b,n);
% get the step delta
h = x(2)-x(1);
v = y(x);
Itrap = (sum(v)-v(1)/2-v(end)/2)*h;
Error = abs(Itrap-Iref);
fprintf('a=%f b=%f len=%d h=%f Error=%f\n',x(1),x(end),length(x),h,Error);
end
When you evaluate the above code, you will notice that a and b are consistent for each iteration, h is roughly what you chose before, and the Error does increase as the step size increases.
Try the above and see what happens!

correct function handle for integral2 in matlab

I created a function in matlab that returns a vector like
function w = W_1D(x,pos,h)
w=zeros(1,length(x));
if (h~=0)
xmpos = x-pos;
inds1 = (-h <= xmpos) & (xmpos < 0);
w(inds1) = xmpos(inds1)./h + 1;
inds2 = (0 <= xmpos) & (xmpos <= h);
w(inds2) = -xmpos(inds2)./h + 1;
else
error('h shouldn't be 0')
end
end
Thus, in the end, there is a vector w of size length(x).
Now i created a second function like
function f = W_2D(x,y,pos_1,pos_2,h)
w_x = W_1D(x,pos_1,h);
w_y = W_1D(y,pos_2,h);
f = w_x'*w_y;
end
where length(x)=length(y). Thus, the function W_2D obviously returns a matrix.
But when I now try to evaluate the integral over a rectangular domain like e.g.
V = integral2(#(x,y) W_2D(x,y,2,3,h),0,10,0,10);
matlab returns some errors:
Error using integral2Calc>integral2t/tensor (line 242)
Integrand output size does not match the input size.
Error in integral2Calc>integral2t (line 56)
[Qsub,esub] = tensor(thetaL,thetaR,phiB,phiT);
Error in integral2Calc (line 10)
[q,errbnd] = integral2t(fun,xmin,xmax,ymin,ymax,optionstruct);
Error in integral2 (line 107)
Q = integral2Calc(fun,xmin,xmax,yminfun,ymaxfun,opstruct);
I also tried to vary something in the W_2D-function: instead of f = w_x'*w_y;
I tried f = w_x.'*w_y;
or w_y = transpose(w_y); f = kron(w_x,w_y);, but there is always this error with the Integrand output size-stuff.
Can anyone explain, where my fault is?
EDIT: After Werner's hint with the keyboard debugging method, I can tell you the following.
The first step returns w_x of type <1x154 double>, w_y is <1x192 double>, x and y are both <14x14 double>. In the next step, f appears with a value of <154x192 double>. Then everything disappears, except x and y and the matlab-function integral2Calc.m appears in the editor and it jumps to the Function Call Stack integral2t/tensor and after some more steps, the error occurs here
Z = FUN(X,Y); NFE = NFE + 1;
if FIRSTFUNEVAL
if ~isfloat(Z)
error(message('MATLAB:integral2:UnsupportedClass',class(Z)));
end
% Check that FUN is properly vectorized. This is important here
% because we (otherwise) always pass in square matrices, which
% reduces the probability of the user generating an error by
% using matrix functions instead of elementwise functions.
Z1 = FUN(X(VTSTIDX),Y(VTSTIDX)); NFE = NFE + 1;
if ~isequal(size(Z),size(X)) || ~isequal(size(Z1),size(VTSTIDX))
% Example:
% integral2(#(x,y)1,0,1,0,1)
error(message('MATLAB:integral2:funSizeMismatch'));
end
Hope that information is detailed enough...I have no idea what happenes, because my example is exact as it is given on the mathworks site about integral2, isn't it?
Maybe I should precise a bit more, what I wanna do: since W_2D gives me a surface w(x,y) of a compactly supported 2-dimensional hat-function, stored in a matrix w, I want to calculate the volume between the (x,y)-plane and the surface z=w(x,y)...
EDIT2: I still do not understand how to handle the problem, that integral2 creates matrices as inputs for my W_1D-functions, which are called in W_2D and intended to have a <1xn double>-valued input and return a <1xn double> output, but at least I can simply use the following to solve the integration over the tensor product by using two one-dimensional integral-calls, that is
V = integral(#(x)integral(#(y)W_1D(y,3,h),0,10).*W_1D(x,2,h),0,10);
This first function is quite wrong. You are not indexing the array positions while you are doing w = x inside for.
Besides, if that would work, you are returning a line vector, that is, size 1xlength(x) and when you do w_x'*w_y you are doing length(x)x1 times 1xlength(y), which would give you a matrix length(x)*length(y).
Consider correcting your function:
function w = W_1D(x,pos)
w = zeros(length(x),1); % Allocate w as column vector, so that the product gives a scalar (as I suppose that it is what you want.
for ii=1:length(x) % Here, so that is indexes w and x elements as you need
w(ii)=x(ii) - pos; % I changed your code to something that makes sense, but I don't know if that is what you want to do, you have to adapt it to work correctly.
end
end
You may also want to debug your functions, consider adding keyboard before your operations and check what they are returning using dbstep. I.e:
function f = W_2D(x,y,pos_1,pos_2)
w_x = W_1D(x,pos_1);
w_y = W_1D(y,pos_2);
keyboard
f = w_x'*w_y;
end
Execution will stop at keyboard, then you can check w_x size, w_y size, and do dbstep to go after f = w_x'*w_y and see what it returned. After you finish debug, you can do dbcont so that it will continue execution.
This answer is a draft as it is quite difficult to help you with the information you have provided. But I think you can start working the things out with this. If you have more doubts feel free to ask.