# How can I scan sets of multi variable in a simple version?

3 views (last 30 days)
Fadhil on 19 Jun 2022
Commented: Jan on 20 Jun 2022
Hello, I am looking for the 4 sets of independent variables(they are actually angles) that satisfies the zero cross product of ure, and uim. However, all i could think is the multi for lopps which has hours of running time in my computer, considering the length of loops. is there any simpler version to get the fast running time? is the multi for loops the best solution? thanks
for phi=0:1:360
for ztj=0:1:180
for phie=0:1:360
for zhet=0:1:180
n=[sind(ztj+1i*zhet)*cosd(phi+1i*phie),sind(ztj+1i*zhet)*sind(phi+1i*phie),cosd(ztj+1i*zhet)];
ure=real(n);uim=imag(n);
if cross(uim,ure)==0
vray=(uim.^2+ure.^2)./ure;
aray=-uim./(uim.^2+ure.^2);
qray=(ure.^2-uim.^2)./(2.*ure.*uim);
else
n=[];ure=[];uim=[];
end
end
end
end
end

Jan on 19 Jun 2022
Edited: Jan on 19 Jun 2022
Take into account rounding errors: testing for cross(x,y)==0 is not stable. Remember, that the output of cross is a vector. So maybe this is a better test:
if all(abs(cross(uim,ure)) < 10 * eps)
The best limit depends on your needs and there is no general "best" choice.
Matlab works slower with complex values than with a pair or real values. This is about 10 times faster than your version:
for phi = 0:36 % Shortend test code
for ztj = 0:18
for phie = 0:36
% c1 = cosd(phi + 1i*phie);
% s1 = sind(phi + 1i*phie);
[c1r, c1i] = cosd_c(phi, phie);
[s1r, s1i] = sind_c(phi, phie);
for zhet = 0:18
% s2 = sind(ztj + 1i * zhet);
[s2r, s2i] = sind_c(ztj, zhet);
[c2r, c2i] = cosd_c(ztj, zhet);
% n = [s2 * c1, ...
% s2 * s1, ...
% cosd(ztj + 1i * zhet)];
% ure = real(n);
% uim = imag(n);
ure = [s2r * c1r - s2i * c1i, ...
s2r * s1r - s2i * s1i, ...
c2r];
uim = [s2r * c1i + s2i * c1r, ...
s2r * s1i + s2i * s1r, ...
c2i];
v = [ uim(2) .* ure(3) - uim(3) .* ure(2), ...
uim(3) .* ure(1) - uim(1) .* ure(3), ...
uim(1) .* ure(2) - uim(2) .* ure(1)];
if all(abs(v) < 10 * eps)
vray = (uim.^2+ure.^2) ./ ure;
aray = -uim ./ (uim.^2+ure.^2);
qray = (ure.^2 - uim.^2) ./ (2.*ure.*uim);
else
n=[];
ure=[];
uim=[];
end
end
end
end
end
function [yr, yi] = sind_c(xr, xi)
xr = xr * 0.0174532925199433;
xi = xi * 0.0174532925199433;
yr = sin(xr) * cosh(xi);
yi = cos(xr) * sinh(xi);
end
function [yr, yi] = cosd_c(xr, xi)
xr = xr * 0.0174532925199433;
xi = xi * 0.0174532925199433;
yr = cos(xr) * cosh(xi);
yi = -sin(xr) * sinh(xi);
end
In addition I've moved the repeated computation of the same value out of the inner loops and replaced the slow cross by an inlined version.
I do not understand the purpose of your code and assume, it is a simplified version only. Do you really overwrite the results repeatedly?
Actually it should be much easier to construct orthogonal vectors directly instead of testing a bunch of vectors if they match the needs.
I admit, that this modification is ugly. But if run time matters, using such methods might be useful.
Jan on 20 Jun 2022
@Fadhil: "actually, ure and uim are not merely a function of n." - Posting too simplified versions of the code and asking for an optimization is a waste of time for the answering persons. I've accelerated a code by a factor of 13.5, but you do not even use this code.
I do not know what "christmat" and "uv" is.
Why do you assume, that the brute force approach with a stepsize of 1° is working? Maybe the directions are not a multiple of 1. A smarter approach would be to perform a global search: find the minima of the crossproducts by an iterative method, a genetic algorithm, simulated annealing, etc.

R2022a

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!