loop has no effect on specific array element - c++

I'm trying to invert a 3x3 matrix. I gauss the augment that has both the original and the identity matrix. Depending on the matrix dimensions, the identity matrix is generated by a separate function with 1s along the main diagonal and 0s everywhere else. Once the operations are complete, the original matrix should be an identity and the identity should be the inverse. I'm able to successfully turn the original into an identity but the something is preventing the original identity from fully becoming the inverse which is confusing because both arrays are inside the same loops.
const int m = 3;
const int n = 3;
double matrix[m][n];
double ID[m][n] = {};
double pivot;
for(s = 1;s <= m;++s){
pivot = matrix[s-1][s-1];
k = s + 1;
for(i = n;i >= 1;--i){ // makes leading entries 1
ID[s-1][i-1] = ID[s-1][i-1]/pivot;
matrix[s-1][i-1] = matrix[s-1][i-1]/pivot;
}
for(j = k;j <= m;++j){ //converts to upper triangular
for(i = n;i >= 1;--i){
ID[j-1][i-1] = ID[j-1][i-1] - ID[s-1][i-1]*matrix[j-1][s-1]; //*****<--- has no effect on ID[2][0]
matrix[j-1][i-1] = matrix[j-1][i-1] - matrix[s-1][i-1]*matrix[j-1][s-1];
}
}
} //ID[2][0] = 0; <--- gives correct answer when uncommented
for(s = m;s >= 1;--s){
k = s - 1;
for(j = k;j >= 1;--j){ //makes entries above diagonal zero
for(i = 1;i <= n;++i){
ID[j-1][i-1] = ID[j-1][i-1] - ID[s-1][i-1]*matrix[j-1][s-1];
matrix[j-1][i-1] = matrix[j-1][i-1] - matrix[s-1][i-1]*matrix[j-1][s-1];
}
}
}
Here's the process by hand, the big arrow points to where I believe my code is getting stuck. ID[2][0] remains as -1 which in turn prevents ID[0][0] from being set to -3 over the final loop.
method with correct result
result without forcing ID(2)[0] to 0
result forcing ID(2)[0] to 0
I don't understand what is going wrong as the loop works fine on matrix[m][n].

Related

Dynamic programming state calculations

Question:
Fox Ciel is writing an AI for the game Starcraft and she needs your help.
In Starcraft, one of the available units is a mutalisk. Mutalisks are very useful for harassing Terran bases. Fox Ciel has one mutalisk. The enemy base contains one or more Space Construction Vehicles (SCVs). Each SCV has some amount of hit points.
When the mutalisk attacks, it can target up to three different SCVs.
The first targeted SCV will lose 9 hit points.
The second targeted SCV (if any) will lose 3 hit points.
The third targeted SCV (if any) will lose 1 hit point.
If the hit points of a SCV drop to 0 or lower, the SCV is destroyed. Note that you may not target the same SCV twice in the same attack.
You are given a int[] HP containing the current hit points of your enemy's SCVs. Return the smallest number of attacks in which you can destroy all these SCVs.
Constraints-
- x will contain between 1 and 3 elements, inclusive.
- Each element in x will be between 1 and 60, inclusive.
And the solution is:
int minimalAttacks(vector<int> x)
{
int dist[61][61][61];
memset(dist, -1, sizeof(dist));
dist[0][0][0] = 0;
for (int total = 1; total <= 180; total++) {
for (int i = 0; i <= 60 && i <= total; i++) {
for (int j = max(0, total - i - 60); j <= 60 && i + j <= total; j++) {
// j >= max(0, total - i - 60) ensures that k <= 60
int k = total - (i + j);
int & res = dist[i][j][k];
res = 1000000;
// one way to avoid doing repetitive work in enumerating
// all options is to use c++'s next_permutation,
// we first createa vector:
vector<int> curr = {i,j,k};
sort(curr.begin(), curr.end()); //needs to be sorted
// which will be permuted
do {
int ni = max(0, curr[0] - 9);
int nj = max(0, curr[1] - 3);
int nk = max(0, curr[2] - 1);
res = std::min(res, 1 + dist[ni][nj][nk] );
} while (next_permutation(curr.begin(), curr.end()) );
}
}
}
// get the case's respective hitpoints:
while (x.size() < 3) {
x.push_back(0); // add zeros for missing SCVs
}
int a = x[0], b = x[1], c = x[2];
return dist[a][b][c];
}
As far as i understand, this solution calculates all possible state's best outcome first then simply match the queried position and displays the result. But I dont understand the way this code is written. I can see that nowhere dist[i][j][k] value is edited. By default its -1. So how come when i query any dist[i][j][k] I get a different value?.
Can someone explain me the code please?
Thank you!

Computing Rand error efficiently

I'm trying to compare two image segmentations to one another.
In order to do so, I transform each image into a vector of unsigned short values, and calculate the rand error,
according to the following formula:
where:
Here is my code (the rand error calculation part):
cv::Mat im1,im2;
//code for acquiring data for im1, im2
//code for copying im1(:)->v1, im2(:)->v2
int N = v1.size();
double a = 0;
double b = 0;
for (int i = 0; i <N; i++)
{
for (int j = 0; j < i; j++)
{
unsigned short l1 = v1[i];
unsigned short l2 = v1[j];
unsigned short gt1 = v2[i];
unsigned short gt2 = v2[j];
if (l1 == l2 && gt1 == gt2)
{
a++;
}
else if (l1 != l2 && gt1 != gt2)
{
b++;
}
}
}
double NPairs = (double)(N*N)/2;
double res = (a + b) / NPairs;
My problem is that length of each vector is 307,200.
Therefore the total number of iterations is 47,185,920,000.
It makes the running time of the entire process is very slow (a few minutes to compute).
Do you have any idea how can I improve it?
Thanks!
Let's assume that we have P distinct labels in the first image and Q distinct labels in the second image. The key observation for efficient computation of Rand error, also called Rand index, is that the number of distinct labels is usually much smaller than the number of pixels (i.e. P, Q << n).
Step 1
First, pre-compute the following auxiliary data:
the vector s1, with size P, such that s1[p] is the number of pixel positions i with v1[i] = p.
the vector s2, with size Q, such that s2[q] is the number of pixel positions i with v2[i] = q.
the matrix M, with size P x Q, such that M[p][q] is the number of pixel positions i with v1[i] = p and v2[i] = q.
The vectors s1, s2 and the matrix M can be computed by passing once through the input images, i.e. in O(n).
Step 2
Once s1, s2 and M are available, a and b can be computed efficiently:
This holds because each pair of pixels (i, j) that we are interested in has the property that both its pixels have the same label in image 1, i.e. v1[i] = v1[j] = p; and the same label in image 2, i.e. v2[i] = v2[ j ] = q. Since v1[i] = p and v2[i] = q, the pixel i will contribute to the bin M[p][q], and the same does the pixel j. Therefore, for each combination of labels p and q we need to consider the number of pairs of pixels that fall into the M[p][q] bin, and then to sum them up for all possible labels p and q.
Similarly, for b we have:
Here, we are counting how many pairs are formed with one of the pixels falling into the bin M[p][q]. Such a pixel can form a good pair with each pixel that is falling into a bin M[p'][q'], with the condition that p != p' and q != q'. Summing over all such M[p'][q'] is equivalent to subtracting from the sum over the entire matrix M (this sum is n) the sum on row p (i.e. s1[p]) and the sum on the column q (i.e. s2[q]). However, after subtracting the row and column sums, we have subtracted M[p][q] twice, and this is why it is added at the end of the expression above. Finally, this is divided by 2 because each pair was counted twice (once for each of its two constituent pixels as being part of a bin M[p][q] in the argument above).
The Rand error (Rand index) can now be computed as:
The overall complexity of this method is O(n) + O(PQ), with the first term usually being the dominant one.
After reading your comments, I tried the following approach:
calculate the intersections for each possible pair of values.
use the intersection results to calculate the error.
I performed the calculation straight on the cv::Mat objects, without converting them into std::vector objects. That gave me the ability to use opencv functions and achieve a faster runtime.
Code:
double a = 0, b = 0; //init variables
//unique function finds all the unique value of a matrix, with an optional input mask
std::set<unsigned short> m1Vals = unique(mat1);
for (unsigned short s1 : m1Vals)
{
cv::Mat mask1 = (mat1 == s1);
std::set<unsigned short> m2ValsInRoi = unique(mat2, mat1==s1);
for (unsigned short s2 : m2ValsInRoi)
{
cv::Mat mask2 = mat2 == s2;
cv::Mat andMask = mask1 & mask2;
double andVal = cv::countNonZero(andMask);
a += (andVal*(andVal - 1)) / 2;
b += ((double)cv::countNonZero(andMask) * (double)cv::countNonZero(~mask1 & ~mask2)) / 2;
}
}
double NPairs = (double)(N*(N-1)) / 2;
double res = (a + b) / NPairs;
The runtime is now reasonable (only a few milliseconds vs a few minutes), and the output is the same as the code above.
Example:
I ran the code on the following matrices:
//mat1 = [1 1 2]
cv::Mat mat1 = cv::Mat::ones(cv::Size(3, 1), CV_16U);
mat1.at<ushort>(cv::Point(2, 0)) = 2;
//mat2 = [1 2 1]
cv::Mat mat2 = cv::Mat::ones(cv::Size(3, 1), CV_16U);
mat2.at<ushort>(cv::Point(1, 0)) = 2;
In this case a = 0 (no matching pairs correspondence), and b=1(one matching pair for i=2,j=3). The algorithm result:
a = 0
b = 1
NPairs = 3
result = 0.3333333
Thank you all for your help!

Find a centroid of a dataset

If I have some random data set let's say
X Y
1.2 16
5.7 0.256
128.54 6.879
0 2.87
6.78 0
2.98 3.7
... ...
x' y'
How can I find the centroid coordinates of this data set?
p.s. Here what I tried but got wrong results
float Dim1[K];
float Dim2[K];
float centroidD1[K];
float centroidD2[K];
int K = 4;
int counter[K];
for(int i = 0; i < K ; i++)
{
Dim1[i] = 0;
Dim2[i] = 0;
counter[i] = 0;
for(int j = 0; j < hash["Cluster"].size(); j++)
{
if(hash["Cluster"].value(j) == i+1)
{
Dim1[i] += hash["Dim_1"].value(j);
Dim2[i] += hash["Dim_2"].value(j);
counter[i]++;
}
}
}
for(int l = 0; l < K; l++)
{
centroidD1[l] = Dim1[l] / counter[l];
centroidD2[l] = Dim2[l] / counter[l];
}
I guess I choose wrong algorithm for doing it, as I get wrong results.
Calculating a sum and dividing by N is not a good idea if you have a large data set. As your floating point accumulator grows adding a new point eventually stop working due to the magnitude difference. An incremental formula might work better, see: https://math.stackexchange.com/questions/106700/incremental-averageing
If the issue is too large a data set you can verify the basic functioning of your code by using a smaller data set with a hand verified result. For example, just 1 data point, or 10 data points.

Generating incomplete iterated function systems

I am doing this assignment for fun.
http://groups.csail.mit.edu/graphics/classes/6.837/F04/assignments/assignment0/
There are sample outputs at site if you want to see how it is supposed to look. It involves iterated function systems, whose algorithm according the the assignment is:
for "lots" of random points (x0, y0)
for k=0 to num_iters
pick a random transform fi
(xk+1, yk+1) = fi(xk, yk)
display a dot at (xk, yk)
I am running into trouble with my implementation, which is:
void IFS::render(Image& img, int numPoints, int numIterations){
Vec3f color(0,1,0);
float x,y;
float u,v;
Vec2f myVector;
for(int i = 0; i < numPoints; i++){
x = (float)(rand()%img.Width())/img.Width();
y = (float)(rand()%img.Height())/img.Height();
myVector.Set(x,y);
for(int j = 0; j < numIterations;j++){
float randomPercent = (float)(rand()%100)/100;
for(int k = 0; k < num_transforms; k++){
if(randomPercent < range[k]){
matrices[k].Transform(myVector);
}
}
}
u = myVector.x()*img.Width();
v = myVector.y()*img.Height();
img.SetPixel(u,v,color);
}
}
This is how my pick a random transform from the input matrices:
fscanf(input,"%d",&num_transforms);
matrices = new Matrix[num_transforms];
probablility = new float[num_transforms];
range = new float[num_transforms+1];
for (int i = 0; i < num_transforms; i++) {
fscanf (input,"%f",&probablility[i]);
matrices[i].Read3x3(input);
if(i == 0) range[i] = probablility[i];
else range[i] = probablility[i] + range[i-1];
}
My output shows only the beginnings of a Sierpinski triangle (1000 points, 1000 iterations):
My dragon is better, but still needs some work (1000 points, 1000 iterations):
If you have RAND_MAX=4 and picture width 3, an evenly distributed sequence like [0,1,2,3,4] from rand() will be mapped to [0,1,2,0,1] by your modulo code, i.e. some numbers will occur more often. You need to cut off those numbers that are above the highest multiple of the target range that is below RAND_MAX, i.e. above ((RAND_MAX / 3) * 3). Just check for this limit and call rand() again.
Since you have to fix that error in several places, consider writing a utility function. Then, reduce the scope of your variables. The u,v declaration makes it hard to see that these two are just used in three lines of code. Declare them as "unsigned const u = ..." to make this clear and additionally get the compiler to check that you don't accidentally modify them afterwards.

How do you multiply a matrix by itself?

This is what i have so far but I do not think it is right.
for (int i = 0 ; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
matrix[i][j] += matrix[i][j] * matrix[i][j];
}
}
Suggestion: if it's not a homework don't write your own linear algebra routines, use any of the many peer reviewed libraries that are out there.
Now, about your code, if you want to do a term by term product, then you're doing it wrong, what you're doing is assigning to each value it's square plus the original value (n*n+n or (1+n)*n, whatever you like best)
But if you want to do an authentic matrix multiplication in the algebraic sense, remember that you had to do the scalar product of the first matrix rows by the second matrix columns (or the other way, I'm not very sure now)... something like:
for i in rows:
for j in cols:
result(i,j)=m(i,:)·m(:,j)
and the scalar product "·"
v·w = sum(v(i)*w(i)) for all i in the range of the indices.
Of course, with this method you cannot do the product in place, because you'll need the values that you're overwriting in the next steps.
Also, explaining a little bit further Tyler McHenry's comment, as a consecuence of having to multiply rows by columns, the "inner dimensions" (I'm not sure if that's the correct terminology) of the matrices must match (if A is m x n, B is n x o and A*C is m x o), so in your case, a matrix can be squared only if it's square (he he he).
And if you just want to play a little bit with matrices, then you can try Octave, for example; squaring a matrix is as easy as M*M or M**2.
I don't think you can multiply a matrix by itself in-place.
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
product[i][j] = 0;
for (k = 0; k < 5; k++) {
product[i][j] += matrix[i][k] * matrix[k][j];
}
}
}
Even if you use a less naïve matrix multiplication (i.e. something other than this O(n3) algorithm), you still need extra storage.
That's not any matrix multiplication definition I've ever seen. The standard definition is
for (i = 1 to m)
for (j = 1 to n)
result(i, j) = 0
for (k = 1 to s)
result(i, j) += a(i, k) * b(k, j)
to give the algorithm in a sort of pseudocode. In this case, a is a m x s matrix and b is an s x n, the result is a m x n, and subscripts begin with 1..
Note that multiplying a matrix in place is going to get the wrong answer, since you're going to be overwriting values before using them.
It's been too long since I've done matrix math (and I only did a little bit of it, on top), but the += operator takes the value of matrix[i][j] and adds to it the value of matrix[i][j] * matrix[i][j], which I don't think is what you want to do.
Well it looks like what it's doing is squaring the row/column, then adding it to the row/column. Is that what you want it to do? If not, then change it.