Calculate similarity score between multidimensional arrays (Tensor) - arrays

I have two tensors A and B of sizes 1500 x 1000 x 500. how can I calculate similarity index between them?
I have applied the following formula:
relerr = frob((A - B))./frob(A);

It depends on your definition for similarity score.
Simply you can use Euclidean distance as follow:
x = 20;
y = 10;
z = 12;
A = randi([1, 10], x, y, z);
B = randi([1, 10], x, y, z);
C = (A-B).^2;
similarity = sqrt(sum(C(:)));
or you can define other similarity measures like Correlation coefficeint.

Related

Is there an elegant way to sum columns in a Vector of Static arrays in Julia?

I store velocities for particles as a Vector of SVectors. Each row is an SVector with that indices x, y, z velocity.
SVectors are great for their speed in arithmetic, but they are a bit... difficult to manipulate. How would I add up all of the x, y, z squared velocities in my Vector in a way that is more elegant than the following
using StaticArrays
n = 5
v = [SVector{3}(rand(), rand(), rand()) for i = 1:n]
x, y, z = 0.0, 0.0, 0.0
for i=1:n
x += v[i][1]^2
y += v[i][2]^2
z += v[i][3]^2
end
sumv = SVector{3}(x, y, z)
If I just wanted to sum the x, y, z in my velocities, without squaring, Julia is simple, just sum(v) will give me a vector of the summed columns.
One solution I have is
sum([v[i].^2 for i=1:n])
but there must be a simpler solution that doesn't require a comprehension?
The sum function can take a higher order function that transforms each element before it adds them.
julia> sum(x->x.^2, v)
3-element SArray{Tuple{3},Float64,1,3} with indices SOneTo(3):
2.104874346619557
1.2512923674436118
1.5781536056190726
This gives the same answer as your comprehension:
julia> sum(x->x.^2, v) == sum([v[i].^2 for i=1:n])
true
What about SMatrices?
n=5
mat = SMatrix{3, n}([rand() for i = 1:n*3])
sum(mat .^ 2, dims=2)

fsolve with two sets of variables

fsolve solves a problem specified by
F(x)=0
for x. In my case, x is a 2-dimensional array of size m x n. Now suppose
that in addition to x, there is a vector y that needs to be solved for
as well. What is the best way to expand the number of variables fsolve
solves for, given that fsolve only allows for a single argument?
One solution, one that I would like to avoid, is to rewrite the problem in
terms of a single vector with entries of x and y stacked as in
x(1) ... x(m x n), y(1) ... y(m-1)
I would like to avoid this solution because the equations for the first set
of variables can be nicely defined in 2 dimensions.
Would it be possible to create a 3-dimensional array of size m x n x 2 where the first page (the 3rd dimension in Matlab terminology) is the original x-matrix and the entries of y appear on the second page? But then, what is if y is only of size m-1 so that the second page is largely empty? Would this be possible somehow?
EDIT
Here is a simplied version of the model with m=n=2.
The equations in the first set are
x(1,1)*dot(k1,y)-y(1) = 0;
x(1,2)*dot(k2,y)-y(1) = 0;
x(2,1)*dot(k1,y)-y(2) = 0;
x(2,2)*dot(k2,y)-y(2) = 0;
where k1 and k2 are two vectors of parameters.
When m=n=2, the second set of equations consists of a single equation of the form
y(1)*dot(c1,x(1,:)) + y(2)*dot(c2,x(2,:)) = 0
Where c1 and c2 are two vectors of parameters. The last entry of y, here y(2), is always a parameter.
You can combine them into a single vector but you don't need to modify F. For example suppose you have a function F(x, y) where x and y are arbitrarily sized then something like the following should work
function [x, y] = fsolve2(F, x0, y0)
% flatten x0 and y0 into a single column vector
xy0 = [x0(:); y0(:)];
% utility functions for recovering x and y from combined vector
xstart = 1;
xend = xstart + numel(x0) - 1;
xsize = size(x0);
getx = #(xy) reshape(xy(xstart:xend), xsize);
ystart = xend + 1;
yend = ystart + numel(y0) - 1;
ysize = size(y0);
gety = #(xy) reshape(xy(ystart:yend), ysize);
% define G which takes xy and calls F
G = #(xy) F(getx(xy), gety(xy));
xy = fsolve(G, xy0);
% unwrap xy into x and y
x = getx(xy);
y = gety(xy);
end
which could be called with
x, y = fsolve2(F, x0, y0);

Multiplying vectors of uneven length and summing the result

How can I for every element of a vector calculate several elements from another vector?
For example, x=[1,2] and y=[1,2,3,4] then I need to multiply and sum each element of x with all elements of y, like so;
x = [1,2]
y = [1,2,3,4]
z = [x1*y,x2*y] = [x1*y1+x1*y2+x1*y3+x1*y4,x2*y1+x2*y2+x2*y3+x2*y4]
The vectors can have unlimited elements.
x = randi(10,3,1);
y = randi(10,4,1);
tmp = bsxfun(#times,x.',y); % Pre-R2016b
% tmp = x.'*y; % Post R2016b method
out = sum(tmp(:));
One can use either bsxfun or implicit expansion to create a matrix of numel(x) * numel(y) size and then sum over the flattened array to get to a final result.
You can multiply x with sum of y
result = x * sum(y)

2D to 3D with parallel projection

I'm trying to do parallel projection in C.
My function:
void parallel_projection(int x, int y, int z, float angle);
It is necessary to pass 3D coordinates to 2D using the parallel projection with the parameters of the function.
What is the formula to use to find x and y? (Using cos, sin and tangent)
Parallel Projection - Wikipedia
In your image, x and wx is the same axis, and angle is in yoz plane. So wx = x.
projected y:
when y = 0,
wy = z * cos(pi/2 - α) = z * sin(α)
when y > 0 and z < 0,
wy = sqrt(y^2 + z^2) * cos(α + arctan(z / y) + pi)
otherwise,
wy = sqrt(y^2 + z^2) * cos(α + arctan(z / y))
Note that angle is given in degree, while in C, trigonometric functions accept radian.

how to increase the possibility of getting a specific random object from an array

Generally, I know that I can get a random element of an array in the following way:
var myArray = [x, y, z]
let myArrayLength = UInt32(myArray.count)
let myArrayIndex = Int(arc4random_uniform(myArrayLength))
let randomElement = myArray[myArrayIndex]
But how can I make the possibility of y being the random element twice the possibility of x and z being the random element thrice the possibility of y?
UPDATE
NB: Where x, y and z are CGPoints
An easy way is to rewrite your array like this: [x,x,y,z]. Then, the probability of getting x becomes 0.5, the probability of y becomes 0.25 and the probability of z becomes 0.25. Just repeat the symbols with high probability as much as you want, for example [x, y, y, z, z, z, z] is good for what you asked for.

Resources