find the intersection of two array structs in Matlab - algorithm

How can I find the following intersection of two array structs in Matlab.
For example, I have two struct arrays a and b:
a(1)=struct('x',1,'y',1);
a(2)=struct('x',3,'y',2);
a(3)=struct('x',4,'y',3);
a(4)=struct('x',5,'y',4);
a(5)=struct('x',1,'y',5);
b(1)=struct('x',1,'y',1);
b(2)=struct('x',3,'y',5);
I want to find the intersection of a and b as follows:
c = intersect(a,b)
where c should be
c = struct('x',1,'y',1);
But when it seems wrong when I type intersect(a,b) since the elements of a and b are both structures. How can I combat this difficulty. Thanks.

The elegant solution would have been to supply intersect with a comparator operator (like in , e.g., C++).
Unfortunaetly, Matlab does not seem to support this kind of functionality/flexibility.
A workaround for your problem would be
% convert structs into matrices
A = [[a(:).x];[a(:).y]]';
B = [[b(:).x];[b(:).y]]';
% intersect the equivalent representation
[C, ia, ib] = intersect( A, B, 'rows' );
% map back to original structs
c = a(ia);
Alternatively, have you considered replacing your structs with class objects derived from handle class? It might be possible to overload the relational operators of the class and then it should be possible to sort the class objects directly (I haven't looked closely into this solution - it's just a proposal off the tip of my head).

A more general variant of Shai's approach is:
A = cell2mat(permute(struct2cell(a), [3 1 2]));
B = cell2mat(permute(struct2cell(b), [3 1 2]));
[C, ia] = intersect(A, B, 'rows');
c = a(ia);
This way you don't need to explicitly specify all the struct fields. Of course, this won't work if the struct fields contain non-numeric values.
Generalized approach for fields of any type and dimensions
If you're uncertain about the type and size of the data stored in your structs, interesect won't cut it. Instead, you'll have to use isequal with a loop. I'm using arrayfun here for elegancy:
[X, Y] = meshgrid(1:numel(a), 1:numel(b));
c = a(any(arrayfun(#(m, n)isequal(a(m), b(n)), X, Y)));

A systematic approach would be to produce a hash - and then use intersect:
hash_fun = #(x) sprintf('x:%g;y:%g',x.x,x.y);
ha = arrayfun(hash_fun,a,'UniformOutput',false);
hb = arrayfun(hash_fun,b,'UniformOutput',false);
[hi,ind_a,ind_b]=intersect(ha,hb)
res=a(ind_a) % result of intersection

Related

Resorting and holding a vector

So this is probably a very specific problem and i am not sure if it is even solvable but here we go:
I have a vector with 6 indices which each are variables. These variables get calculated separately. What I want now is that the order of the indices changes at a specific time and stays like that. But the actual value of the indices needs to keep being calculated. Maybe explaining it in my Modelica code helps with understanding.
I have a vector with six indices, made up out of 6 variables, let's name them A to F. A to F are each calculated in a different way which is (probably) not relevant here so I'm simply writing [...] for that here. They behave independently of each other.
Real Vector[6];
Real A;
Real B;
Real C;
Real D;
Real E;
Real F;
equation
A = 3*x;
B = 5-x +7/x ...;
C = [and so on]
D = [...]
E = [...];
F = [...];
Initially, the Vector is sorted like this:
Vector = {A, B, C, D, E, F};
But I want the order of the indices to be resorted via some if-clauses every 100 seconds (starting at time=0) which i make work like that:
when sample(0,100) then
Vector = {if xyz then A,
elseif xyz then B ....}
end when;
Again, the specific way in which i resort the indices (probably) doesn't matter because it definitely works.
My problem is: While it does resort my Vector every 100 seconds and holds this new order/sequence (which is exactly what i need), it of course also holds the calculated actual values of A to F at that time. Which means i get constant values between each time step.
What i need is the new order to hold but the values of A to F need to keep being calculated.
I also tried using if instead of when like
if time <100 then Vector = {A, B, C, D, E, F}
elseif time >=100 and <200 then Vector = {if xyz then A, elseif xyz then B ....(see above)}
else ...;
end if;
Problem here: it does also resort my Vector while also calculating A to F. But it looks to resort my vector all the time, not only once every 100 seconds --> holding the order until the next 100 seconds are over (the resorting is dependent on other calculated values in the model which are constantly changing).
My model is very huge so it's tricky to share all the parts that weave into this part of my work which is the reason i had to simplify my explanations as much as possible. I hope someone can help me with this.
I'm still relatively new at this and have been mostly teaching myself for the last few months so maybe I'm simply not aware of an easy obvious solution here. Or what I need is simply not doable in Modelica.
Thank you!
Not 100% sure I got the question correctly, but would the the graph below show what you need?
...with v being the original vector and vs being the continuously computed, but sorted (ascending every 100s) version of v.
This is the respective code:
model VectorSorting "Computes 'vs' every 100s from 'v' with acending order"
Real A, B, C, D, E, F; // Some variables computed in equations below
Real v[6]; // vector for A...F
Real vs[6]; // sorted version of 'v'
Integer i[6](start=1:6, fixed=true); // indexes of vector
Real d[6](start=zeros(6), fixed=true); // dummy variable
equation
A = time+200;
B = time-150;
C = 3*time-333;
D = 0.5*time+75;
E = -250;
F = 750;
v = {A, B, C, D, E, F};
vs = v[i];
when sample(0, 100) then
(d, i) = Modelica.Math.Vectors.sort(v);
end when;
annotation (experiment(StopTime=500), uses(Modelica(version="4.0.0")));
end VectorSorting;

How do I calculate inner product of two vectors in nalgebra?

From the following
let v = OVector::<f64, U2>::from_column_slice(&[3_f64, 4_f64]);
let x = &v.transpose() * &v; // get the inner product, i.e. <v,v>
I expected x to be a f64 scalar, i.e. x = 25.0.
But actually, I can only obtain x as OMatrix::<f64, Cosnt<1>, Const<1>>.
The case can be even worse in matrix product operations. for example, the following code doesn't work since v^T v is not a scalar.
let m = OMatrix::<f64, U2, U2>::from_element(1.0);
let v = OVector::<f64, U2>::from_column_slice(&[3_f64, 4_f64]);
// not working
let y = &v.transpose() * &v * m; // types conflict
// working
let y = 25.0 * m; // expected to behave like this
What is the correct way to do this?
Usually, in maths, you would identify 1x1 matrices with scalars (because, for some definition of being equivalent, they are equivalent...). When doing this, the dot product of two vectors is exactly the dot product between two matrices, when we see vectors as matrix columns (which are also equivalent for some equivalence...).
However, here, it is not the case: Rust has to know what is the type of the data. So, I would suggest, since you are using matrices to start with, to use the actual matrix dot product, not the vector one. It's simply (v.transpose()*v).trace(). This is a more general dot product, but notice taking the trace will exactly "extract" the scalar from the 1x1 matrix.
Otherwise, this operation is already defined as the dot product (unsurprisingly): v.dot(v).

How is `(d*a)mod(b)=1` written in Ruby?

How should I write this:
(d*a)mod(b)=1
in order to make it work properly in Ruby? I tried it on Wolfram, but their solution:
(da(b, d))/(dd) = -a/d
doesn't help me. I know a and b. I need to solve (d*a)mod(b)=1 for d in the form d=....
It's not clear what you're asking, and, depending on what you mean, a solution may be impossible.
First off, (da(b, d))/(dd) = -a/d, is not a solution to that equation; rather, it's a misinterpretation of the notation used for partial derivatives. What Wolfram Alpha actually gave you was:
, which is entirely unrelated.
Secondly, if you're trying to solve (d*a)mod(b)=1 for d, you may be out of luck. For any value of a and b, where a and b have a common prime factor, there are an infinite number of values of d that satisfy the equation. If a and b are coprime, you can use the formula given in LutzL's answer.
Additionally, if you're looking to perform symbolic manipulation of equations, Ruby is likely not the proper tool. Consider using a CAS, like Python's SymPy or Wolfram Mathematica.
Finally, if you're just trying to compute (d*a)mod(b), the modulo operator in Ruby is %, so you'd write (d*a)%(b).
You are looking for the modular inverse of a modulo b.
For any two numbers a,b the extended euclidean algorithm
g,u,v = xgcd(a, b)
gives coefficients u,v such that
u*a+v*b = g
and g is the greatest common divisor. You need a,b co-prime, preferably by ensuring that b is a prime number, to get g=1 and then you can set d=u.
xgcd(a,b)
if b = 0
return (a,1,0)
q,r = a divmod b
// a = q*b + r
g,u,v = xgcd(b, r)
// g = u*b + v*r = u*b + v*(a-q*b) = v*a+(u-q*v)*b
return g,v,u - q*v

Matlab: replace values in one matrix with another matrix according to their referenced locations

I have two geotiff images (saying "A" and "B") imported in Matlab as matrices with Geotiffread. One has different values, while the second has only 0 and 255s.
What I'd like to do is replacing all the 255s with the values inside the other image (or matrix), according to their positions.
A and B differs in size, but they have the same projections.
I tried this:
A (A== 255)= B;
the output is the error:
??? In an assignment A(:) = B, the number of elements in A and B must be the same.
Else, I also tried with the logical approach:
if A== 255
A= B;
end
and nothing happens.
Is there a way to replace the values of A with values of B according to a specific value and the position in the referenced space?
As darthbith put in his comment, you need to make sure that the number of entries you want to replace is the same as the number values you are putting in.
By doing A(A==255)=B you are trying to put the entire matrix B into the subset of A that equals 255.
However, if, as you said, the projections are the same, you can simply do A(A==255) = B(A==255), under the assumption that B is larger or the same size as A.
Some sample code to provide a proof of concept.
A = randi([0,10],10,10);
B = randi([0,4],15,15);
C = A % copy original A matrix for comparison later
A(A==5) = B(A==5); % replace values
C==A % compare original and new
This example code creates two matrices, A is a 10x10 and B is a 15x15 and replaces all values that equal 5 in A with the corresponding values in B. This is shown to be true by doing C==A which shows where the new matrix and the old matrix vary, proving replacement did happen.
It seems to me that you are trying to mask an image with a binary mask. You can do this:
BW = im2bw(B,0.5);
A=A.*BW;
hope it helps
Try A(A==255) = B(A==255). The error is telling you that when you try to assign values to the elements of an array, you cannot give it any more or fewer values than you are trying to assign.
Also, regarding the if statement: if A==255 means the same as if all(A==255), as in, if any elements of A are not 255, false is returned. You can check this at the command line.
If you're really desperate, you can use a pair of nested for loops to achieve this (assuming A and B are the same size and shape):
[a,b] = size(A);
for ii = 1:a
for jj = 1:b
if A(ii,jj) == 255
A(ii,jj) = B(ii,jj);
end
end
end

What is the name of this geometrical function?

In a two dimentional integer space, you have two points, A and B. This function returns an enumeration of the points in the quadrilateral subset bounded by A and B.
A = {1,1} B = {2,3}
Fn(A,B) = {{1,1},{1,2},{1,3},{2,1},{2,2},{2,3}}
I can implement it in a few lines of LINQ.
private void UnknownFunction(Point to, Point from, List<Point> list)
{
var vectorX = Enumerable.Range(Math.Min(to.X, from.X), Math.Abs(to.X - from.Y) + 1);
var vectorY = Enumerable.Range(Math.Min(to.Y, from.Y), Math.Abs(to.Y - from.Y) + 1);
foreach (var x in vectorX)
foreach (var y in vectorY)
list.Add(new Point(x, y));
}
I'm fairly sure that this is a standard mathematical operation, but I can't think what it is.
Feel free to tell me that it's one line of code in your language of choice. Or to give me a cunning implementation with lambdas or some such.
But mostly I just want to know what it's called. It's driving me nuts.
It feels a little like a convolution, but it's been too long since I was at school for me to be sure.
It's the Cartesian product of the sets {1,2} and {1,2,3} in your specific example, or generally the Cartesian product of the vectorX and vectorY in your code example.
I don't know that this is a standard mathematical operation, if you wanted to describe it mathematically it would be described as such.
Given two points, (x_1,x_2) and (y_1,y_2) in N^2. Then take min_1 to be min(x_1,y_1) and max_1 to be max(x_1,y_1) and symetric operations for min_2 and max_2. Then the set is defined as:
Enum = { (a,b) : a,b in N^2 and min_1 <= a <= max_1 and min_2 <= b <= max_2 }
Which seems pretty arbitrary to me and I would say that it doesn't seem like a fairly standard mathematical operation to me.
Solving it using the Cartesian product becomes, trickier. It was simple to use the cartesian product when you have points that are so close together, but what about when you have {1,1} and {8,8}. Then the problem is a little more involved. You take the two sets:
{ a: min(x_1,y_1) <= a <= max(x_1,y_1) } and {b : min(x_2,y_2) <= b <= max(x_2,y_2) }
In both instances you're simply taking all the values in the range and enumerating across the space. Once again though, it feels like an arbitrary operation and maybe I'm wrong, but I don't think this has a well-known name. Besides enumerating the points in a rectangle.
Integer / lattice points in bounds / rectangle.
(Similar to the name of http://en.wikipedia.org/wiki/Integer_points_in_convex_polyhedra)
Cartesian Product using list comprehensions in
Python
[(x,y) for x in [1,2] for y in [1,2,3] ]
and Haskell
[(x,y) | x <- [1,2] , y <- [1,2,3] ]

Resources