Map matrix elements to {0, 1} values in EJML - ejml

I would like to turn a matrix of non-negative integers to a binary matrix. For example, given the following input matrix:
2 3
0 1
It should the following output matrix:
1 1
0 1
I think this is similar to a map operation, so pseudocode-wise this operation is equivalent to mapElements(x -> (x > 0) ? 1 : 0) or simply mapNonZeroes(x -> 1).
A possible approach is to unfurl the non-zero elements of the matrix to triplets with the value set to 0/1 and rebuild the matrix from the triplets. Is there a better way to do this?

For me what worked is to directly access the nz_values storage field, and map the values myself.
public void normalizeMatrix(DMatrixSparseCSC m) {
for (int i = 0; i < m.nz_length; i++) {
m.nz_values[i] = Math.min(m.nz_values[i], 1.0);
}
}

Related

Eigen3 (cpp) select column given mask and sum where true

I have a Eigen::Matrix2Xf where row are X and Y positions and cols act as list index
I would like to have the sum of the columns (rowwise) where some column condition is true, here some example code:
Eigen::Vector2f computeStuff(Eigen::Matrix2Xf & values, const float max_norm){
const auto mask = values.colwise().norm().array() < max_norm;
return mask.select(values.colwise(), Eigen::Vector2f::Zero()).rowwise().sum();
}
But this code does not compile complaining about the types of the if/else matrices, what is the correct (and computationally faster) way to do it?
Also I know that there are similar question with an answer, but they create a new Eigen::Matrix2Xf with the filtered values given the mask, this code is meant to run inside a #pragma omp parallel for so the basic idea is to do not create a new matrix for maintaining cache coherency
Thanks
The main problem with your code is that .select( ... ) needs at least one of its arguments to have the same shape as the mask. The arguments can be two matrices or a matrix and a scalar or vice-versa, but in all cases the matrices have to be shaped like the mask.
In your code mask is a row vector but values is a 2 by x matrix. One way to handle this is to just replicate the row vector into a two row matrix:
#include <Eigen/Dense>
#include <iostream>
Eigen::Vector2f computeStuff(Eigen::Matrix2Xf& values, const float max_norm) {
auto mask = (values.colwise().norm().array() < max_norm).replicate(2, 1);
return mask.select(values, 0).rowwise().sum();
}
int main() {
Eigen::Matrix2Xf mat(2,4);
mat << 1, 4, 3, 2,
1, 2, 4, 3;
auto val = computeStuff(mat, 5);
std::cout << val;
return 0;
}
In the above mask will be:
1 1 0 1
1 1 0 1
i.e. the row 1 1 0 1 duplicated once. Then mask.select(values, 0) yields
1 4 0 2
1 2 0 3
so the result will be
7
6
which i think is what you want, if I am understanding the question.

Convert vector to OpenCV Matd1d in c++

I have a variable M that is a cv::Mat1d matrix. It is made like this:
cv::Mat1d<double> M;
It is populated with a bunch of values in some other code that is probably not necessary and it looks like this when I print it:
[-0.9344576352096885;
-0.9344576352096885;
-0.5766199600499906;
0.2846686026510846;
0.9589011777015718;
0.9285453673591227;
0.3137239980297359;
-0.2302718892981206;
-0.2921750731112262;
-0.2206633656711884;
-0.2175072323850435;
-0.1725991485554647;
-0.2140556050785325;
-0.4148403958730175;
-0.4036417215304363;
-0.06016889338878993;
0.3028103268622913;
0.4454375499811856;
0.3803583582813156;
0.3188387192279333;
0.3914868895364941;
0.4488724871465618;
0.2694705005556897;
-0.05248136866304744;
-0.2971598882254832;
-0.3545797186279719;
-0.2294426230118397;
-0.1673776410980104;
-0.2768386357175945;
-0.3276029287776189;
-0.2361695287135101;
-0.06139424097086685;
0.1621769468562924;
0.3275221571852822;
0.3153071221383847;
0.1341365194415481;
-0.04596232030582767;
-0.08961855126383761;
-0.02999823421387905;
-0.03225119207066054]
It is size [1 x 40].
I had to convert M to a vector X to do some calculations on it. I converted it like this:
vector<ld> X;
X.push_back(M.at<double>(0, 0));
for (int i = 1; i < M.rows; i++) {
X.push_back(M.at<double>(i, 0));
}
Now when I print it (After the calculations I did which are irrelevant), it looks like this:
[0 0 0 0 0 -1 -1 0 1 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 1 0 0]
and is size 40.
How do I convert X back to a [1x40] cv::Mat1d so that it is the same type as M?
Note: If my question/syntax/anything else is appalling, my apologies. I am just now leaving the relative safety of python for c++...
Edit
I think I solved it. In case anyone is curious OR if my solution needs correcting, here it is:
Mat1d test;
for (int i = 0; i < X.size(); i++) {
double new_val = (double) X[i];
test.push_back(new_val);
}
I'm not sure I quite understand what you need. You are doing two things here,
dealing with type conversion between integer and floating point types
reshaping the arrays between row and column vector
cv::Mat::reshape is a little different from numpy's reshape but does the same thing. you could have two Mats sharing the same data, and you use the one for a row view and the other for a column view.
cv::Mat m1_column, m2_row;
m2_row = m1_column.reshape(0, 1);
// first arg: number of channels. 0 means same.
// second arg: number of rows. make it a row vector.
cv::Mat::convertTo is roughly equivalent to numpy's ndarray.astype. it copies the values, converted to the desired type, into another cv::Mat.
cv::Mat m1_floats, m2_ints, m3_floats;
m1_floats.convertTo(m2_ints, CV_8U);
m2_ints.convertTo(m3_floats, CV_32F);
combine both as you need.
you don't even need to move between column and row format. just use a single index in Mat::at<>(). it'll run through the matrix as if it were flattened.
you can construct a Mat from a std::vector so it shares the vector's memory:
std::vector<int> X; // contains values from somewhere, ints should be 32 bit
cv::Mat X_as_a_Mat(1, X.size(), CV_32S, X.data()); // a single-row Mat sharing the std::vector's data
cv::Mat X_as_doubles;
X_as_a_Mat.convertTo(X_as_doubles, CV_64F); // converts data type
this code assumes that int is a 32 bit signed type (CV_32S). I don't know what element type your vector<ld> is supposed to be.

Numbers of common distinct difference

Given two array A and B. Task to find the number of common distinct (difference of elements in two arrays).
Example :
A=[3,6,8]
B=[1,6,10]
so we get differenceSet for A
differenceSetA=[abs(3-6),abs(6-8),abs(8-3)]=[3,5,2]
similiarly
differenceSetB=[abs(1-6),abs(1-10),abs(6-10)]=[5,9,4]
Number of common elements=Intersection :{differenceSetA,differenceSetB}={5}
Answer= 1
My approach O(N^2)
int commonDifference(vector<int> A,vector<int> B){
int n=A.size();
int m=B.size();
unordered_set<int> differenceSetA;
unordered_set<int> differenceSetB;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
differenceSetA.insert(abs(A[i]-A[j]));
}
}
for(int i=0;i<m;i++){
for(int j=i+1;j<m;j++){
differenceSetB.insert(abs(B[i]-B[j]));
}
}
int count=0;
for(auto &it:differenceSetA){
if(differenceSetB.find(it)!=differenceSetB.end()){
count++;
}
}
return count;
}
Please provide suggestions for optimizing the approach in O(N log N)
If n is the maximum range of a input array, then the set of all differences of a given array can be obtained in O(n logn), as explained in this SO post: find all differences in a array
Here is a brief recall of the method, with a few additional practical implementation details:
Create an array Posi of length 2*n = 2*range = 2*(Vmax - Vmin + 1), where elements whose index matches an element of the input are set to 1, other elements are set to 0. This can be created in O(m), where m is the size of the array.
For example, given in input array [1,4,5] of size m, we create an array [1,0,0,1,1].
Initialisation: Posi[i] = 0 for all i (i = 0 to 2*n)
Posi[A[i] - Vmin] = 1 (i = 0 to m)
Calculate the autocorrelation function of array Posi[]. This can be classically performed in three sub-steps
2.1 Calculate the FFT (size 2*n) of Posi[]array: Y[] = FFT(Posi)
2.2 Calculate the square amplitude of the result: Y2[k] = Y[k] * conj([Y[k])
2.3 Calculate the Inverse FFT of the result Diff[] = IFFT (Y2[])`
A few details are worth being mentioned here:
The reason why a size 2*n was selected, and not a size n, if that, is d is a valid difference, then -d is also a valid difference. The results corresponding to negative differences are available at positions i >= n
If you find more easy to perform FFT with a size a-power-of-two, than you can replace the size 2*n with a value n2k = 2^k, with n2k >= 2*n
The non-null differences correspond to non-null values in the array Diff[]:
`d` is a difference if `Diff[d] > 0`
Another important details is that a classical FFT is used (float calculations), then you encounter little errors. To take it into account, it is important to replace the IFFT output Diff[] with integer rounded values of the real part.
All that concerns one array only. As you want to calculate the number of common differences, then you have to:
calculate the arrays Diff_A[] and Diff_B[] for both sets A and B and then:
count = 0;
if (Diff_A[d] != 0) and (Diff_B[d] != 0) then count++;
A little Bonus
In order to avoid a plagiarism of the mentioned post, here is an additional explanation about the way to get the differences of one set, with the help of the FFT.
The input array A = {3, 6, 8} can mathematically be represented by the following z transform:
A(z) = z^3 + z^6 + z^8
Then the corresponding z-transform of the difference array is equal to the polynomial product:
D(z) = A(z) * A(z*) = (z^3 + z^6 + z^8) (z^(-3) + z^(-6) + z^(-8))
= z^(-5) + z^(-3) + z^(-2) + 3 + z^2 + z^3 + z^5
Then, we can note that A(z) is equal to a FFT of size N of the sequence [0 0 0 1 0 0 1 0 1] by taking:
z = exp (-i * 2 PI/ N), with i = sqrt(-1)
Note that here we consider the classical FFT in C, the complex field.
It is certainly possible to perform calculation in a Galois field, and then no rounding errors, as it is done for example to implement "classical" multiplications (with z = 10) for a large number of digits. This seems over-skilled here.

Splitting a massive matrix into blocks

I have a problem. I'm working on a task that tries to find a matrix (vector) inside another matrix(vector) and the size of the matrices are:
Massive Matrix: 1024x768
Small Matrix: 36x49
Basically, my theory was to split the massive matrix into blocks that were the size of the small matrix thus meaning I was able to just see whether the small matrix exists in which block and then output the block. However, it just will not split equally but I need a way to determine if the small matrix does actually exist in the massive matrix.
As an example, I'll use test data:
M1 =
0 1 0 0
1 1 1 1
0 0 0 0
1 0 1 1
M2 =
0 1
1 1
And then I would split the matrices into blocks of 2x2 and then check that way. This is simple as I'm only working with a small matrix AND the matrix can be split equally, whereas the problem above is a lot more complex to understand and figure out.
In essence, I need to be able to split the (1024x768) into block sizes of (36x49) so then I can do the check to determine where that particular matrix is. I have been working with this algorithm:
// Assume:
// matrix1ColSize = 768
// matrix2ColSize = 49
const int ROW_BOUNDS = matrix1.size() - matrix2.size();
const int COL_BOUNDS = matrix1ColSize - matrix2ColSize;
bool found = false;
for(int i=0; (i < ROW_BOUNDS); i++)
{
bool matchFound = false;
for(int j=0; (j < COL_BOUNDS); j++) {
// logic here
}
cout << endl;
}
Could anyone offer any advice please? This is really annoying me now :(!
Two matrices are the same if all their elements are the same. So the following pseudo-code compares the small matrix with a block in the large matrix:
Initialize result to "true"
For each position in the small matrix
Read the value from the large matrix; call it x1
Read the value from the small matrix; call it x2
If x1 is not equal to x2, set result to "false"
(Optional) If x1 is not equal to x2, stop looking at other positions
Here, use the result
This logic is going to be inside your 2 nested loops, so you will have 4 nested loops there! If you fear of getting confused, put the implementation inside a function. If you want to use 4 nested loops, good luck.
In c++:
bool is_equal = true;
for (int y = 0; y < 49; ++y)
{
for (int x = 0; x < 36; ++x)
{
if (matrix1.at(j + x, i + y) != matrix2.at(x, y))
{
is_equal = false;
goto DONE; // optional
}
}
}
DONE:;
Edit: this code assumes using a custom class for matrices; after looking again at your code i realize that you probably use a vector of vectors (std::vector<std::vector<int>>), so use matrix2[y][x] instead of matrix2.at(x, y).

Logical Question

Consider a [4x8] matrix "A" and [1x8] matrix "B". I need to check if there exists a value "X" such that
[A]^T * [X] = [B]^T exists for any x >= 0 { X is a [4X1] matrix, T = transpose }
Now here is the trick/tedious part. The matrix A always has 1 as its diagonal. A11,A22,A33,A44 = 1 This matrix can be considered as two halves with first half being the first 4 columns and the second half being the second 4 columns like something below :
1 -1 -1 -1 1 0 0 1
A = -1 1 -1 0 0 1 0 0
-1 -1 1 0 1 0 0 0
-1 -1 -1 1 1 1 0 0
Each row in the first half can have either two or three -1's and if it has two -1's then that corresponding row in the second half should have one "1" or if any row has three -1's the second half of the matrix should have two 1's. The overall objective is to have the sum of each row to be 0.
Now B is a [1x8] matrix which can also be considered as two halves as follows:
B = -1 -1 0 0 0 0 1 1
Here there can be either one, two, three or four -1's in the first half and there should be equal number of 1's in the second half. It should be done in combinations For example, if there are two -1's in the first half, they can be placed in 4 choose 2 = 6 ways and for each of them there will be 6 ways to place the 1's in the second half which has a total of 6*6 = 36 ways. i.e. 36 different values for B's if there are two -1's in the first half. The placement of 1's in the matrix A should also be the same way. The way I could think of doing this is to consider a valarray or something of that sort and make the matrices A and B but I don't know what to do.
Now for every A, I've to test it with every combinations of B to see if there exists
[A]^T * [X] = [B]^T
I'm trying to prove a result that I got I need to know if such an X would exist or not. I'm very confused on implementing this. Any suggestions are welcome. This would come under linear programming concept in math. I want it either in C++ or in Matlab. Any other languages are also acceptable but I'm familiar with only these two. Thanks in advance.
Update:
Here is my answer for this problem :
clear;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%# Generating all possible values of vector B
%# permutations using dec2bin (start from 17 since it's the first solution)
vectorB = str2double(num2cell(dec2bin(17:255)));
%# changing the sign in the first half, then check that the total is zero
vectorB(:,1:4) = - vectorB(:,1:4);
vectorB = vectorB(sum(vectorB,2)==0,:);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%# generate all possible variation of first/second halves
z = -[0 1 1; 1 0 1; 1 1 0; 1 1 1]; n = -sum(z,2);
h1 = {
[ ones(4,1) z(:,1:3)] ;
[z(:,1:1) ones(4,1) z(:,2:3)] ;
[z(:,1:2) ones(4,1) z(:,3:3)] ;
[z(:,1:3) ones(4,1) ] ;
};
h2 = arrayfun(#(i) unique(perms([zeros(1,4-i) ones(1,i)]),'rows'), (1:2)', ...
'UniformOutput',false);
%'# generate all possible variations of complete rows
rows = cell(4,1);
for r=1:4
rows{r} = cell2mat( arrayfun( ...
#(i) [ repmat(h1{r}(i,:),size(h2{n(i)-1},1),1) h2{n(i)-1} ], ...
(1:size(h1{r},1))', 'UniformOutput',false) );
end
%'# generate all possible matrices (pick one row from each to form the matrix)
sz = cellfun(#(M)1:size(M,1), rows, 'UniformOutput',false);
[X1 X2 X3 X4] = ndgrid(sz{:});
matrices = cat(3, ...
rows{1}(X1(:),:), ...
rows{2}(X2(:),:), ...
rows{3}(X3(:),:), ...
rows{4}(X4(:),:) );
matrices = permute(matrices, [3 2 1]); %# 4-by-8-by-104976
A = matrices;
clear matrices X1 X2 X3 X4 rows h1 h2 sz z n r
options = optimset('LargeScale','off','Display','off');
for i = 1:size(A,3),
for j = 1:size(vectorB,1),
X = linprog([],[],[],A(:,:,i)',vectorB(j,:)');
if(size(X,1)>0) %# To check that it's not an empty matrix
if((size(find(X < 0),1)== 0)) %# to check the condition X>=0
if (A(:,:,i)'* X == (vectorB(j,:)'))
X
end
end
end
end
end
I got it with the help of stackoverflow folks. The only problem is the linprog function throws a lot of exceptions in every iteration along with the answers produced. The exception is:
(1)Exiting due to infeasibility: an all-zero row in the constraint matrix does not have a zero in corresponding right-hand-side entry.
(2) Exiting: One or more of the residuals, duality gap, or total relative error has stalled: the primal appears to be infeasible (and the dual unbounded).(The dual residual < TolFun=1.00e-008.
What does this mean. How can I overcome this?
It is not clear from your question if you are familiar with system linear equations and their solution, or it is what you are trying to "invent". See also here for Matlab-specific explanation.
If you are familiar with that, you should be more clear in your question about what makes your problem different.