Eigen: how to remove an initialised coefficient from a sparse Matrix - c++

I am writing a backward elimination algorithm. At each iteration I need to eliminate some coefficients from a column of a SparseMatrix and update the other non zero ones.
However, changing a reference to a coefficient to zero does not deallocate it, so the number of non zero coefficients is the same. How do I delete the reference? I tried with makeCompressed() to no avail and pruned is not known by the compiler.
Basic code below.
How can I solve this problem?
#include <Eigen/SparseCore>
void nukeit(){
Eigen::SparseMatrix<double> A(4, 3);
cout << "non zeros of empty: " << A.nonZeros() << "\n" << endl;
A.insert(0, 0) = 1;
A.insert(2, 1) = 5;
cout << "non zeros are two: " << A.nonZeros() << "\n" << endl;
A.coeffRef(0, 0) = 0;
cout << "non zeros should be one but it's 2: " << A.nonZeros() << "\n" << endl;
cout << "However the matrix has only one non zero element\n" << A << endl;
}
Output
non zeros of empty: 0
non zeros are two: 2
non zeros should be one but it's 2: 2
However the matrix has only one non zero element
0 0 0
0 0 0
0 5 0
0 0 0

After setting some of the coefficients of the current column to zero, you can explicitly remove them by calling A.prune(0.0). See the respective doc.
However, be aware that this will trigger a costly memory copy of the remaining column entries. With sparse matrices, we usually never work in-place.

Related

Weird mistake in taking the sums of elements in alglib::real_1d_array

OK this time I have a really weird mistake that does not always appear. Here is the function that actually contains problems. All it does is literally summing elements of a vector. It works in most cases but in a few cases it tend to become highly problematic.
int sumvec(vect v) {
int i = 0;
int sum = 0;
int l = v.length();
std::cout << "Sum of vector " << v.tostring(3) << std::endl;
for (; i < l; i++) {
sum += v[i];
std::cout << v[i] << " " << sum << " ";
};
std::cout << std::endl;
return sum;
}
Here vect is defined using typedef alglib::real_1d_array vect;. OK so what do I get? Huh..
Sum of vector [1.000,1.000,0.000,1.000,1.000,1.000]
1 0 1 0 0 0 1 0 1 0 1 1
What?!!!!!
As your sum variable is an integer you may not get the expected results when summing elements in your vector which are not integers.
If your elements have the value of 0.999999999 rather than 1.00000 then printing them could be rounded to 1.00000 but when you add them to an integer the value will be truncated to 0.
Judging by the provided output all of your values are less than 1 apart from the last one which is greater or equal to 1.
There are 2 possible solutions:
Change the type of sum to be float or double.
Change your calculation to: sum += static_cast<int>(round( v[i] ));
Note that your compiler was probably warning about the truncation of a double to an integer. Pay attention to compiler warnings, they often indicate a bug.
As commented use a double to store the sum if you are working with floating point integers. using an integer will cause the variable to be implicitely casted to an int which just cuts of the mantissa:
0.9999998 -> 0
Depending on cout::precision, 0.99999 would be printed as 1.0000(rounded) or without std::fixed just as 1 what propably happens in your example.
double a = 0.999;
std::cout.precision(2);
std::cout << a << std::endl; /* This prints 1 */
std::cout << std::fixed;
std::cout << a << endl; /* This prints 1.00 */

C++ giving a negative number when I square

So I have some code that is supposed to be giving me the points on a parabola but the problem is that when I square the number when it is a negative it gives me a negative back which wont work.
#include "TileClass.h"
//#include <cmath> included in other header
// Original equation y=-x^2+4
void Tile::Loc() {
for (int a = -2; a < 3; a = a + 1) {
cout << "--- " << a << endl;
cout << "Pw" << (a << 2) << endl;
cout << ((a << 2) + 4) << endl;
}
}
output
--- -2
Pw-8
-4
--- -1
Pw-4
0
--- 0
Pw0
4
--- 1
Pw4
8
--- 2
Pw8
12
The C++ operator << is not the square operator. It is the bitshift operator.
Try
-(a*a)+4
instead
The express a<<2 will shift each bit of a to left by 2, which means a*4
And if you want to get the square of a, you had better use a*a.
it doesn't look like you're squaring. You're left shifting the binary value which is essentially the same as multiplying by 2 per left shift. So when a = -2, doing (a << 2) should result in -8 being displayed. What you are looking for is the pow() function found in the cmath library which should be used like this pow(a, 2);

Cosine similarity using Armadillo C++ gives me negative results

I have implmented a cosine similarity function which uses armadillo c++ linear library. My code is the next one:
double cosine_similarity(rowvec A, rowvec B)
{
double dot = as_scalar(A*B.t());
double denomA = as_scalar(A*A.t());
double denomB = as_scalar(B*B.t());
return dot / (sqrt(denomA) * sqrt(denomB)) ;
}
I have this matrix as an example:
-0.0261 -0.6780 -0.7338 0.0345
-0.0230 0.0082 -0.0400 -0.7056
-0.2590 -0.7052 0.6590 -0.0371
-0.9650 0.2072 -0.1551 0.0426
-0.0230 0.0082 -0.0400 -0.7056
When I calculate the cosine similarity between the second row vs all the rows i get the following results:
Similarity [1,0]: -1.07944e-16
Similarity [1,1]: 1
Similarity [1,2]: -1.96262e-17
Similarity [1,3]: -1.71729e-16
Similarity [1,4]: 1
Is this correct? Am worrying about the negative results even when what they mean is zero. I am wondering if I am doing something wrong. cosine_similarity is used in this way:
for (unsigned int row = 0; row < redV.n_rows ; row++)
{
double ans = cosine_similarity(redV.row(indicate), redV.row(row));
cout << "Similarity [" << indicate << "," << row << "]: " << ans << endl;
cout << "Similarity [" << indicate << "," << row << "]: " << norm_dot(redV.row(indicate), redV.row(row)) << endl;
}
Your code seems right, you’re just encountering machine precision issues. A*B.t() for A the third row and B for the second row (or vice versa) should be zero but isn’t, but is within machine precision. Scipy’s cosine has the same problem:
In [10]: from scipy.spatial.distance import cosine
In [11]: 1 - cosine([-0.2590, -0.7052, 0.6590, -0.0371], [-0.0230, 0.0082, -0.0400, -0.7056])
Out[11]: -1.114299639159988e-05 # <=============== should not be negative!
(I subtract by 1 just because of how Scipy defines cosine. And this answer doesn’t match yours because you posted only four decimal points—but the punchline is, it’s negative.)
If you want to check whether a floating point number x is within machine precision of another y, compare their difference with std::numeric_limits::epsilon. See the definition of almost_equal here. You might want cosine_similarity to check if the result is almost_equal to 0 or 1, in which case return 0 or 1.

This program should give the AND of the following numbers. What does this mean?

For an assignment in my C++ programming class, I was given the following code. The assignment simply says "This program should give the AND of the following numbers" Was wondering if could get clarification on the meaning. I have an idea but I think I still need a bit of advice. The code was provided jumbled on purpose which I had to clear up. Here is is cleaned up:
// Question2
// This program should give the AND of the inputted numbers.
#include <iostream>
//**Needs namespace statement to directly access cin and cout without using std::
using namespace std;
//**Divided up statements that are running together for better readability
//**Used more spacing in between characters and lines to further increase readability
////void main()
//**Main function should include int as datatype; main is not typically defined as a void function
int main()
{
int i;
int k;
//**Changed spacing to properly enclose entire string
cout << "Enter 0 (false) or 1 (true) for the first value: " << endl;
cin >> i;
cout<< "Enter 0 (false) or 1 (true) for the second value: " << endl;
cin >> k;
//**Spaced out characters and separated couts by lines
//**to help with readability
cout << "AND" << endl;
cout << "k\t| 0\t| 1" << endl;
cout << "---\t| ---\t| ---" << endl;
cout << "0\t| 0\t| 0" << endl;
cout << "1\t| 0\t| 1" << endl;
if(i==1&k==1)
cout <<"Result is TRUE" << endl;
else cout << "Result is FALSE" <<endl;
//**Main function typically includes return statement of 0 to end program execution
return 0;
}
Every number has a binary representation. They're asking for the logical and of the bits. Look up the & operator.
'&' is a bitwise and, which means it takes the binary representation of two numbers and compares each bit in the first number against the bit in the same position on the second. If both are 1, the resultant bit in the same position in the output number is 1, otherwise the bit is zero. if (i&k) would have the same result (assuming the input was always 0 or 1), but anyway your if statement compares whether the first bit is 0 or 1, and if both are 1 returns one.
the AND gate(output) will be true only if both inputs are true(1)
true if i==1 && k==1
false if i==0 && k==0,i==1 && k==0,i==0 && k==1.

c++ vector not updating in nested for loop

So I create and initialize a vector (of size nmask+3) to 0, and I assign an initial value to one of the elements. I then make a for loop that goes through the first nmask elements of the vector and assigns to each element an average of 26 other elements in the vector (defined by the 4D int array voxt, which contains vector addresses).
My problem is that when I check the values of nonzero elements in my vector (phi) within the nested loop (the first cout), the values are fine and what I expect. However, when the loop finishes going through all nmask elements (for (int i= 0; i<nmask; i++) exits), I check the nonzero elements of phi again, and they are all lost (reset to 0) except for the last non-zero element (and element tvox which is manually set to 1).
I feel that since phi is initialized outside of all the loops, there should be no resetting of values going on, and that any updated elements within the nested loop should remain updated upon exit of the loop. Any ideas as to what is going on / how to fix this? Code is below; I tried to comment in a sense of the outputs I'm getting. Thanks in advance.
vector<double> phi(nmask+3, 0); //vector with nmask+3 elements all set to 0 (nmask = 13622)
phi[tvox]= 1; //tvox is predefined address (7666)
for (int n= 0; n<1; n++)
{
vector<double> tempPhi(phi); //copy phi to tempPhi
for (int i= 0; i<nmask; i++)
{
for (int a= -1; a<=1; a++)
{
for (int b= -1; b<=1; b++)
{
for (int c= -1; c<=1; c++)
{
if (!(a==0 && b==0 && c==0))
{
//oneD26 is just (double) 1/26
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
if (phi[i]!=0)
{
//this gives expected results: 27 nonzero elements (including tvox)
cout << n << " " << i << " " << a << b << c << " " << phi[i] << endl;
}
}
}
}
}
}
phi[svox]= 0; //svox = 7681
phi[tvox]= 1;
for (int q= 0; q<nmask; q++)
{
//this gives only 2 nonzero values: phi[tvox] and phi[9642], which was the last nonzero value from 1st cout
if (phi[q]!=0)
cout << q << " " << phi[q] << endl;
}
}
Difficult to tell just what is going on, but the easiest explanation is that after phi[i] gets set to non-zero and displayed to cout, it gets set to zero again in one of the later iterations through the inner loops.
If you do some tracing and check phi[i] just before updating you'll see that you often overwrite a non-zero element with zero.
Note: I have no idea what your code does, this is pure Sherlock Holmes reasoning.. if after the loops you find only 2 non-zero elements then the only logical consequence is that after updating something to non-zero later in the loop you update it to zero.
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
The nested for-loops using a, b, and c run for a combined 9 iterations with the same value of i. Since you overwrite phi[i] to a new value every time, you only retain the value from the last iteration where a, and c are all 1. If that last iteration happens to produce zero values, then phi[i] will have lots of zeroes. Perhaps you meant to do something like phi[i] += ... instead of phi[i] = ...?
I do suggest to replace the meat of the loop with something like
const boost::irange domain(-1,2);
for (int i: boost::irange(0, nmask)) for (int a: domain) for (int b: domain) for (int c: domain)
{
if (a==0 && b==0 && c==0)
continue;
//oneD26 is just (double) 1/26
phi[i]= tempPhi[i]+oneD26*tempPhi[voxt[i][1+a][1+b][1+c]];
if (phi[i]!=0)
{
//this gives expected results: 27 nonzero elements (including tvox)
cout << n << " " << i << " " << a << b << c << " " << phi[i] << endl;
}
}
Of course, for brevity I assume both boost/range.hpp and c++0x compiler. However, with trivial macro's you can achieve the same. That is without writing/using a proper combinations algorithm (why is that not in the standard, anyway).