2d interpolation table (Matlab) - matlab

I have a table( w, alfa, eta ):
w = [0, 0.5, 1]
alfa = [0, 0.3, 0.6, 0.9]
eta(0,0.3) = 0.23
eta(0.5,0) = 0.18
eta(0.5,0.6) = 0.65
eta(1,0.9) = 0.47
where, eta = f(w,alfa)
How can I interpolate the data to obtain all values ​​in this table?
I try griddata, interp2 etc but i can't do it.

It seems like griddata should do the work in your case. However, you should notice that your inputs requires extrapolation as well as interpolation.
>> [xout yout] = meshgrid( w, alfa ); % output points
>> w_in = [ 0, 0.5, 0.5, 1 ];
>> a_in = [ 0.3, 0, 0.6, 0.9 ];
>> e_in = [ 0.23, 0.18, 0.65, 0.47 ];
>> eta_out = griddata( w_in, a_in, e_in, xout, yout, 'linear' )

Related

Matlab interp2() gives 'monotonically increasing' error

I have many lines that represent a "z" value and want to interpolate at a specific value between them, at a specific x-axis location, to get the y-value. I'm trying interp2() but it throws a 'monotonically increasing' error.
The dataset below is a subset. I broke it out into xyz-1 and xyz-2 just for easy plotting in this question (i.e., making a repeatable example). How can I fix my interp2() or the inputs?
x1 = [0.02, 0.048, 0.108, 0.196, 0.279, 0.401];
y1 = [0.583, 0.43, 0.32, 0.279, 0.262, 0.259];
z1 = [50, 50, 50, 50, 50, 50];
x2 = [0.02, 0.048, 0.108, 0.196, 0.279, 0.401];
y2 = [0.747, 0.591, 0.435, 0.357, 0.326, 0.305];
z2 = [35, 35, 35, 35, 35, 35];
x_all = [x1, x2];
y_all = [y1, y2];
z_all = [z1, z2];
plot(x1, y1, 'blue', 'DisplayName', 'z1')
hold on
plot(x2, y2, 'magenta', 'DisplayName', 'z2')
xlabel('x')
ylabel('y')
legend
want_x = 0.2;
want_z = 40;
need_y = interp2(x_all, y_all, z_all, want_x, want_z, 'linear')
Error:
Error using griddedInterpolant
The grid vectors must be strictly monotonically increasing.
Error in interp2>makegriddedinterp (line 228)
F = griddedInterpolant(varargin{:});
Error in interp2 (line 128)
F = makegriddedinterp({X, Y}, V, method,extrap);
The function griddata is your friend for these tasks, It uses scatteredInterpolant under the hood, but in my opinion is more user friendly.
Keeping the same example code you gave, replacing the last line with:
>> need_y = griddata(x_all,z_all,y_all,want_x, want_z)
need_y =
0.329506024096386
The function can take vector inputs for want_x and want_z and return a vector output of need_y if you need to query more than one point.
You can also specify the interpolation method (linear, cubic, etc ...).
And just to make sure it worked as desired:
>> F = scatteredInterpolant(x_all.', z_all.', y_all.', 'linear'); %NOT y_all, z_all
need_y = F(want_x, want_z)
need_y =
0.329506024096386 % same result, yay!
For more details about using griddata, you can have a look at my answer to this question extremely similar to yours (just worded a bit differently): Interpolation between two curves (matlab)
You can interpolate the value with:
x1 = [0.02, 0.04, 0.09, 0.184, 0.309, 0.667];
y1 = [0.586, 0.447, 0.34, 0.279, 0.256, 0.256];
z1 = [50, 50, 50, 50, 50, 50];
x2 = [0.022, 0.044, 0.076, 0.125, 0.184, 0.293, 0.509, 0.667];
y2 = [0.747, 0.6, 0.49, 0.41, 0.363, 0.326, 0.303, 0.3];
z2 = [35, 35, 35, 35, 35, 35, 35, 35];
want_x = 0.2;
want_z = 40;
y1_ = interp1(x1, y1, want_x);
y2_ = interp1(x2, y2, want_x);
want_y = interp1([50 35], [y1_ y2_], want_z);
This question was answered here:
https://www.mathworks.com/matlabcentral/answers/637955-interp2-monotonically-increasing-error
quoting from that answer, in case the link breaks in the future:
interp2() is only for two-dimensional interpretation over a grid, not for interpolation of vectors. You need something like
F = scatteredInterpolatn(x_all, z_all, y_all, 'linear'); %NOT y_all, z_all
need_y = F(want_x, want_z);

Looping through points in the unit triangle

I have a problem where I have two choice variables x1 and x2 which then pin down a third x3 = 1 - x1 - x2. I would like to loop through various values of [x1, x2, x3]. This code works:
w1 = perms([0.1, 0.1, 0.8]);
w2 = perms([0.1, 0.2, 0.7]);
w3 = perms([0.1, 0.3, 0.6]);
w4 = perms([0.1, 0.4, 0.5]);
w5 = perms([0.2, 0.2, 0.6]);
w6 = perms([0.2, 0.3, 0.5]);
w7 = perms([0.2, 0.4, 0.4]);
w8 = perms([0.3, 0.3, 0.4]);
w = [w1; w2; w3; w4; w5; w6; w7; w8];
w = unique(w,'rows');
% loop
for ii = 1:size(w, 1)
... do some stuff with w(ii, :)
but I am wondering if there is a more elegant way to do this.
This is a classical case for ndgrid
[x1,x2]=ndgrid(0.1:0.1:0.8,0.1:0.1:0.8);
x3 = 1-x1-x2;
%I assume from your example that we want x1,x2,x3 in (0,1) OPEN interval, then:
valid_points = x3>0 & x3 <1
w_prime = [x1(valid_points),x2(valid_points),x3(valid_points)];

fminsearch for non linear regression Matlab?

Can anyone explain to me how I can apply fminsearch to this equation to find the value of K (Diode Equality Factor) using the Matlab command window.
I = 10^-9(exp(38.68V/k)-1)
I have data values as follows:
Voltage := [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]:
Current:= [0, 0, 0, 0, 0, 0, 0, 0.07, 0.92, 12.02, 158.29]:
I used fminsearch and an error message appeared:
Matrix dimensions must agree.
Error in #(k)sum((I(:)-Imodel(V(:),k)).^2)
Error in fminsearch (line 189)
fv(:,1) = funfcn(x,varargin{:});
I used this fminsearch code:
V = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0];
I = [0, 0, 0, 0, 0, 0, 0.07 ,0.92 ,12.02 ,158.29];
Imodel = #(V,k) 1E-9*(exp(38.68*V/k)-1);
k0 = 1;
kmodel = fminsearch(#(k) sum((I(:)-Imodel(V(:),k)).^2), k0)
Please explain what the problem in this code is?
It looks like you are carrying on from this post: Fminsearch Matlab (Non Linear Regression ). The linked post is trying to find the right coefficient k in your equation that minimizes the sum of squared errors between the input, which is predicted current from the current-voltage relation of a diode and the output, which is the measured current from a diode. This current post is simply trying to get that off the ground.
In any case, this is a very simple error. You're missing an element in your current array I. It's missing one 0. You can verify this by using numel on both V and I. Basically, V and I don't match in size. numel(V) == 11 and numel(I) == 10.
The definition you have at the top of your question compared to how you defined your error, it's missing one final zero:
I = [0, 0, 0, 0, 0, 0, 0, 0.07, 0.92, 12.02, 158.29];
%// ^
When I run the code with this new I, I get:
>> kmodel
kmodel =
1.4999

Fminsearch Matlab (Non Linear Regression )

Can anyone explain to me how I can apply non linear regression to this equation t find out K using the matlab command window.
I = 10^-9(exp(38.68V/k)-1).
Screenshot of Equation
I have data values as follows:
Voltage := [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]:
Current:= [0, 0, 0, 0, 0, 0, 0, 0.07, 0.92, 12.02, 158.29]:
Screenshot of Equation
[NEW]: Now I used FminSearch as an alternative another and another error message appeared.
Matrix dimensions must agree.
Error in #(k)sum((I(:)-Imodel(V(:),k)).^2)
Error in fminsearch (line 189)
fv(:,1) = funfcn(x,varargin{:});
I used this fminsearch code:
>> V = [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0];
>> I = [0, 0, 0, 0, 0, 0, 0.07 ,0.92 ,12.02 ,158.29];
>> Imodel = #(V,k) 1E-9*(exp(38.68*V/k)-1);
>> k0 = 1;
>> kmodel = fminsearch(#(k) sum((I(:)-Imodel(V(:),k)).^2), k0)
>> kmodel = fminsearch(#(k) sum((I(:)-Imodel(V(:),k)).^2), k0);
You want to find the parameter k that will minimize the sum of squared error of your exponential model (BTW, is that a current/voltage characteristic?) given the current data I and voltage data V as vectors:
Imodel = #(V,k) 1E-9*(exp(38.68*V/k)-1);
k0 = 1;
kmodel = fminsearch(#(k) sum((I(:)-Imodel(V(:),k)).^2), k0);
plot(V(:), I(:), 'ok', V(:), Imodel(V(:),kmodel), '-r');
The anonymous function calculates the sum of squared error. The search for the parameter k that will minimize the model error starts with the value 1; please change it to a more appropriate value (if you have a good guess for it).

DTMC Markov Chain - How to get the stationary vector

For a Discrete Time Markov Chain problem, i have the following:
1) Transition matrix:
0.6 0.4 0.0 0.0
0.0 0.4 0.6 0.0
0.0 0.0 0.8 0.2
1.0 0.0 0.0 0.0
2) Initial probability vector:
1.0 0.0 0.0 0.0
So, i wrote the following SciLab code to get to the stationary vector:
P = [0.6, 0.4, 0, 0; 0, 0.4, 0.6, 0; 0, 0, 0.8, 0.2; 1,0,0,0]
PI = [1,0,0,0]
R=PI*P
count=0;
for i = 1 : 35 // stationary vector is obtained at iteration 33, but i went futher to be sure
R=R*P;
count=count+1
disp("count = "+string(count))
end
PI // shows initial probability vector
P // shows transition matrix
R // shows the resulting stationary vector
After iteration number 33, the following resulting stationary vector is obtained:
0.2459016 0.1639344 0.4918033 0.0983607
What manual calculations do i have to perform in order to get to the stationary vector above without having to multiply the transition matrix 33 times then multiply the result by the initial vector?
I was told that the calculations are quite simple but i just could not realize what to do even after reading some books.
Of course explanations are welcome, but above all things i would like to have the exact answer for this specific case.
You can solve DTMC on Octave by using this short code:
P = [
0.6, 0.4, 0, 0;
0, 0.4, 0.6, 0;
0, 0, 0.8, 0.2;
1, 0, 0, 0
]
pis = [P' - eye(size(P)); ones(1, length(P))] \ [zeros(length(P), 1); 1]
Or with SAGE with this code:
P = matrix(RR, 4, [
[0.6, 0.4, 0, 0],
[ 0, 0.4, 0.6, 0],
[ 0, 0, 0.8, 0.2],
[ 1, 0, 0, 0]
])
I = matrix(4, 4, 1); # I; I.parent()
s0, s1, s2, s3 = var('s0, s1, s2, s3')
eqs = vector((s0, s1, s2, s3)) * (P-I); eqs[0]; eqs[1]; eqs[2]; eqs[3]
pis = solve([
eqs[0] == 0,
eqs[1] == 0,
eqs[2] == 0,
eqs[3] == 0,
s0+s1+s2+s3==1], s0, s1, s2, s3)
On both, the result of the steady state probabilities vector is:
pis =
0.245902
0.163934
0.491803
0.098361
I hope it helps.
WBR,
Albert.