Matlab: how to use an array in dsolve function? - arrays

I have an ODE system of two equations, but want to minimize it with using just one equation with the result of the other.
1)
t=linspace(0,2,3);
syms x(t) y(t);
inits='x(0)=2,y(0)=0';
[x,y]=dsolve('Dx=y','Dy=(y*2)-x', inits)
x = 2*exp(t) - 2*t*exp(t);
y = -2*t*exp(t)
xx=eval(vectorize(x));
xx = 2.0000; 0; -14.7781
yy=eval(vectorize(y));
yy = 0; -5.4366; -29.5562
After I had got the results, I tried to solve it just with one equation and use xx array in Dy equation.
2)
inits='y(0)=0';
[y]=dsolve('Dy=(y*2)-xx', inits);
y = xx/2 - (xx*exp(2*t))/2
yy=eval(vectorize(y));
yy = 0; 0; 396.0397
The values are not the same as it was in the first example. How to get the same result using array?

One problem seems to be that variable xx is not symbolic, so the symbolic solver appears to be considering it as a constant.
A bigger problem is that you really haven't identified how exactly you want matlab to treat the xx values as a continuous function, when it's merely a vector of three points! The fact that you are even expecting the output to be the same for the second case indicates some kind of misunderstanding to me.
But to make this definite, lets assume that you want it to treat xx as a ZOH (zero order held) continuous signal. To handle this symbolically I believe you would need to construct the ZOH signal explicitly using Heaviside functions.
Alternative you could solve it numerically using ode45 for example
t = [0,1,2];
xx = [2, 0, -14.7781];
dydy = #(t,y) 2*y - xx(1+trunc(t));
y = ode45(dydt, [0,2], 0);
This will return yy values of [0, -6.39, -47.21] at the t values of [0, 1, 2] respectively.
This corresponds well with the theoretical values (calculated by hand) of [0, 1-e^2, e^2-e^4] for the ZOH system.
As you can see the above answer is much more in line with your original solution of yy = [0, -5.4366, -29.5562]. Naturally however the two systems differ, as the first one was fed with a continuous time exponential signal whereas the second system was fed with a very coarsely sampled approximation!
You make the two more similar by sampling at a faster rate (finer time interval), and also by interpolating the intersample points with something better than a ZOH.
Update:
Thank you. Maybe can you help me with creating ZOH continuous signal? How to do that?
In the above example I created a ZOH in my derivative function (dydx) by using the three given points in the xx vector and accessing these using "xx(1+trunc(t))". This uses trunc (truncate) to explicitly hold the input constant during the inter-sample (non integer) times.
Seeing as your ODE is linear, you could also use the matlab function "lsim()" which allows you to directly specify the time vector and input vector, and also to directly specify the type of input interpolation (including ZOH, which is actually the default).
For example:
t=[0,1,2]
x=[2,0,-2*e^2]
num=-1
den=[1,-2]
mytf = tf(num,den)
y = lsim(mytf,x,t,0,'zoh');
As with my previous ode45 numerical solution, this gives the identical solution of,
y = [0.00000; -6.38906; -47.20909]
Update (again)
Thank you. Maybe can you help me with creating ZOH continuous signal? How to do that?
Re the symbolic solver. I don't have access to the Matlab symbolic library, but if you really want to use the symbolic solver, then as I explained previous, you can construct a continuous time ZOH signal using the heaviside (unit step) function. Something like the following should do it:
syms xzoh(t)
xzoh = xx(1)*heaviside(t) + (xx(2)-xx(1))*heaviside(t-1) + (xx(3)-xx(2))*heaviside(t-2)

Related

Theory of arrays in Z3: (1) model is difficult to understand, (2) do not know how to implement functions and (3) difference with sequences

Following to the question published in How expressive can we be with arrays in Z3(Py)? An example, I expressed the following formula in Z3Py:
Exists i::Integer s.t. (0<=i<|arr|) & (avg(arr)+t<arr[i])
This means: whether there is a position i::0<i<|arr| in the array whose value a[i] is greater than the average of the array avg(arr) plus a given threshold t.
The solution in Z3Py:
t = Int('t')
avg_arr = Int('avg_arr')
len_arr = Int('len_arr')
arr = Array('arr', IntSort(), IntSort())
phi_1 = And(0 <= i, i< len_arr)
phi_2 = (t+avg_arr<arr[i])
phi = Exists(i, And(phi_1, phi_2))
s = Solver()
s.add(phi)
print(s.check())
print(s.model())
Note that, (1) the formula is satisfiable and (2) each time I execute it, I get a different model. For instance, I just got: [avg_a = 0, t = 7718, len_arr = 1, arr = K(Int, 7719)].
I have three questions now:
What does arr = K(Int, 7719)] mean? Does this mean the array contains one Int element with value 7719? In that case, what does the K mean?
Of course, this implementation is wrong in the sense that the average and length values are independent from the array itself. How can I implement simple avg and len functions?
Where is the i index in the model given by the solver?
Also, in which sense would this implementation be different using sequences instead of arrays?
(1) arr = K(Int, 7719) means that it's a constant array. That is, at every location it has the value 7719. Note that this is truly "at every location," i.e., at every integer value. There's no "size" of the array in SMTLib parlance. For that, use sequences.
(2) Indeed, your average/length etc are not related at all to the array. There are ways of modeling this using quantifiers, but I'd recommend staying away from that. They are brittle, hard to code and maintain, and furthermore any interesting theorem you want to prove will get an unknown as answer.
(3) The i you declared and the i you used as the existential is completely independent of each other. (Latter is just a trick so z3 can recognize it as a value.) But I guess you removed that now.
The proper way to model such problems is using sequences. (Although, you shouldn't expect much proof performance there either.) Start here: https://microsoft.github.io/z3guide/docs/theories/Sequences/ and see how much you can push it through. Functions like avg will need a recursive definition most likely, for that you can use RecAddDefinition, for an example see: https://stackoverflow.com/a/68457868/936310
Stack-overflow works the best when you try to code these yourself and ask very specific questions about how to proceed, as opposed to overarching questions. (But you already knew that!) Best of luck..

MATLAB: Improving for-loop

I need to multiply parts of a column vector with a fixed row vector. I solved this problem using a for-loop. However, I am wondering if the performance can be improved as I have to perform this kind of computation around 50 million times. Here's my code so far:
multMat = 1:5;
mat = randi(5,10,1);
windowSize = 5;
vout = nan(10,1);
for r = windowSize : 10
vout(r) = multMat * mat( (r - windowSize + 1) : r);
end
I was thinking about uisng arrayfun. However, first I don't know how to adress the cell range (i.e. the previous five cells including the current cell), and second, I am not sure if arrayfun will be any faster than using the loop?
This sliding vector multiplication you're describing is an example of what is known as convolution. The following produces the same result as the loop in your example:
vout = [nan(windowSize-1,1);
conv(mat,flip(multMat),'valid')];
If your output doesn't really need the leading NaN values which aren't overwritten in your loop then the conv expression is sufficient without concatenating the NaN elements to it.
For sufficiently large vectors this is of course not guaranteed to be as fast as you'd like it to be, but MATLAB's built-in convolution implementation is likely to be pretty close to an optimal tool for the job.

Matlab: Difference bettween two different sized arrays

Is it possible to find the difference beetwen two arrays of different size?
My problem is that I have two arrays, that scaled are pretty similar and I need the error in each point.
The data look like this:-
Yaw data is much bigger than Yaw Ref.
You could take a very naive approach and simply pad each element of the reference array. That is fairly simple to do:
n = length(yaw)/length(yaw_ref);
yaw_ref_pad = zeros(length(yaw), 1);
for j = 1:length(yaw_ref)-1
yaw_ref_pad((n*j):(n*(j+1)) = yaw_ref(j);
end
You could also do something more adaptive, which may or may not be what you want. This approach uses the derivatives to determine where the padded reference should switch. This might be considered a bit circular, since your system looks like an overdamped PID system and this uses the output to seed the input.
yaw_ref_pad = zeros(length(yaw), 1);
[x, peaks] = findpeaks(diff(yaw));
for j = 1:length(peaks)-1
yaw_ref_pad(peaks(j):peaks(j+1)) = yaw_ref(j);
end
Either way, after filling yaw_ref_pad, your result is simply
error = yaw_ref_pad - yaw;

Matrix calculations without loops in MATLAB

I have an issue with a code performing some array operations. It is too slow, because I use loops and input data are quite big. It was the easiest way for me, but now I am looking for something faster than for loops. I was trying to optimize or rewrite code, but unsuccessful. I really aprecciate Your help.
In my code I have three arrays x1, y1 (coordinates of points in grid), g1 (values in the points) and for example their size is 300 x 300. I treat each matrix as composition of 9 and I make calculation for points in the middle one. For example I start with g1(101,101), but I am using data from g1(1:201,1:201)=g2. I need to calculate distance from each point of g1(1:201,1:201) to g1(101,101) (ll matrix), then I calculate nn as it is in the code, next I find value for g1(101,101) from nn and put it in N array. Then I go to g1(101,102) and so on until g1(200,200), where in this last case g2=g1(99:300,99:300).
As i said, this code is not very efficient, even I have to use larger arrays than I gave in the example, it takes too much time. I hope I explain enough clearly what I expect from the code. I was thinking of using arrayfun, but I have never worked with this function, so I don't know how should use it, however it seems to me it won't handle. Maybe there are other solutions, however I couldn't find anything apropriate.
tic
x1=randn(300,300);
y1=randn(300,300);
g1=randn(300,300);
m=size(g1,1);
n=size(g1,2);
w=1/3*m;
k=1/3*n;
N=zeros(w,k);
for i=w+1:2*w
for j=k+1:2*k
x=x1(i,j);
y=y1(i,j);
x2=y1(i-k:i+k,j-w:j+w);
y2=y1(i-k:i+k,j-w:j+w);
g2=g1(i-k:i+k,j-w:j+w);
ll=1./sqrt((x2-x).^2+(y2-y).^2);
ll(isinf(ll))=0;
nn=ifft2(fft2(g2).*fft2(ll));
N(i-w,j-k)=nn(w+1,k+1);
end
end
czas=toc;
For what it's worth, arrayfun() is just a wrapper for a for loop, so it wouldn't lead to any performance improvements. Also, you probably have a typo in the definition of x2, I'll assume that it depends on x1. Otherwise it would be a superfluous variable. Also, your i<->w/k, j<->k/w pairing seems inconsistent, you should check that as well. Also also, just timing with tic/toc is rarely accurate. When profiling your code, put it in a function and run the timing multiple times, and exclude the variable generation from the timing. Even better: use the built-in profiler.
Disclaimer: this solution will likely not help for your actual problem due to its huge memory need. For your input of 300x300 matrices this works with arrays of size 300x300x100x100, which is usually a no-go. Still, it's here for reference with a smaller input size. I wanted to add a solution based on nlfilter(), but your problem seems to be too convoluted to be able to use that.
As always with vectorization, you can do it faster if you can spare the memory for it. You are trying to work with matrices of size [2*k+1,2*w+1] for each [i,j] index. This calls for 4d arrays, of shape [2*k+1,2*w+1,w,k]. For each element [i,j] you have a matrix with indices [:,:,i,j] to treat together with the corresponding elements of x1 and y1. It also helps that fft2 accepts multidimensional arrays.
Here's what I mean:
tic
x1 = randn(30,30); %// smaller input for tractability
y1 = randn(30,30);
g1 = randn(30,30);
m = size(g1,1);
n = size(g1,2);
w = 1/3*m;
k = 1/3*n;
%// these will be indexed on the fly:
%//x = x1(w+1:2*w,k+1:2*k); %// size [w,k]
%//y = x1(w+1:2*w,k+1:2*k); %// size [w,k]
x2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
y2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
g2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
%// manual definition for now, maybe could be done smarter:
for ii=w+1:2*w %// don't use i and j as variables
for jj=k+1:2*k %// don't use i and j as variables
x2(:,:,ii-w,jj-k) = x1(ii-k:ii+k,jj-w:jj+w); %// check w vs k here
y2(:,:,ii-w,jj-k) = y1(ii-k:ii+k,jj-w:jj+w); %// check w vs k here
g2(:,:,ii-w,jj-k) = g1(ii-k:ii+k,jj-w:jj+w); %// check w vs k here
end
end
%// use bsxfun to operate on [2*k+1,2*w+1,w,k] vs [w,k]-sized arrays
%// need to introduce leading singletons with permute() in the latter
%// in order to have shape [1,1,w,k] compatible with the first array
ll = 1./sqrt(bsxfun(#minus,x2,permute(x1(w+1:2*w,k+1:2*k),[3,4,1,2])).^2 ...
+ bsxfun(#minus,y2,permute(y1(w+1:2*w,k+1:2*k),[3,4,1,2])).^2);
ll(isinf(ll)) = 0;
%// compute fft2, operating on [2*k+1,2*w+1,w,k]
%// will return fft2 for each index in the [w,k] subspace
nn = ifft2(fft2(g2).*fft2(ll));
%// we need nn(w+1,k+1,:,:) which is exactly of size [w,k] as needed
N = reshape(nn(w+1,k+1,:,:),[w,k]); %// quicker than squeeze()
N = real(N); %// this solution leaves an imaginary part of around 1e-12
czas=toc;

Dynamic programming with sets

I have a typical question in dynamic programming.
My question is given an array = {1,2,3,4,5,6}, I have to find all the arrays whose sum is atmost k. If I consider all the sets, it will become exponential alogorthm. I thought of achiveng this by Dynamic Programming.
Suppose f k =7,
My idea is
Pass 1: {1],{2}....{6}
Pass 2: Pass1 + {1,2},{1,3},{1,4},{1,5}
Pass 3: Pass2 + {1,2,3},
And my algo stops.
Im not able to formulate this with dynamic programming. Any inputs?? How to formulate this algo into program?
A DP solution for the problem should follow the next recursive formula, and build bottom-up:
f(i,0) = {{}} //a set containing only an empty set
f(0,W) = {{}} (W > 0)
f(0,W) = {} (W < 0) //an empty set
f(i,W) = f(i-1,W) [union] extend(f(i-1,w-element[i]),element[i])
Where the function extend(set,e) is:
extend(set,e):
for each s in set: //s is a set itself
s.add(e)
Note that complexity could still be exponential (and not even pseudo-polynomial), since the number of sets generated could be exponential, and is stored in the DP table.
your problem is an instance of the knapsack problem whose related decision problem is known to be NP-complete. this means that most certainly there will be no sub-exponential algorithm (though a mathematical proof is missing ).
ZachLangleys comment shows that the enumeration of all solutions would still be exponential in the worst case even if there was an efficient problem solver since producing the output already requires exponential time.
since the decision problem is NP-complete, counting can not be easier (otherwise you'd count and afterwards test the result whether it equals 0 or not).

Resources