Matrix Addition

Pages: 12
Mar 10, 2020 at 1:41am
So I have a question that I can't figure out involving matrices. It goes as follows:

Complete the implementations for the class Matrix in the file Matrix.cpp. You should only modify
Matrix.cpp and submit only Matrix.cpp to CCLE.
• num rows represents the number of rows in the Matrix object;
• num cols represents the number of columns in the Matrix object;
• vector<vector<int> > values stores all the entries in the matrix.
• The default constructor creates a matrix class object with zero dimensions.
• The other constructor initializes a matrix using user supplied number of rows and number of columns,
and sets the entries of the matrix to be random integer numbers from 0 to 9.
• operator + is overloaded to perform matrix addition with two matrix objects.
Say A and B are two matrices. In order to be able to add them, they both have to have the same
number of rows and the same number of columns. For example, if A has 3 rows and 5 columns then
B has to also have 3 rows and 5 columns. If the dimensions of the two matrices do not match, print
“Dimensions don’t match!” to the console. Otherwise, perform matrix addition entry-wise and return
the result as a Matrix object.
• void print(ofstream& fout) const outputs a Matrix object to a file as requested by the user.
A sample output in the text file for 3 × 5 matrices defined in the main function is something like:
4 5 2 7 9
6 1 8 6 3
4 9 1 5 1
9 1 2 5 1
3 6 7 9 4
9 3 7 3 1
13 6 4 12 10
9 7 15 15 7
13 12 8 8 2

The following are the given files:
Matrix.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
#include <vector>
#include <fstream>
#include <cstdlib>
#include <ctime>

using namespace std;

class Matrix
{
public:
	Matrix();
	Matrix(int new_num_rows, int new_num_cols);
	
	Matrix operator+ (const Matrix& M2) const;
	
	void print(ofstream& fout) const;

private:
	int num_rows;
	int num_cols;
	vector<vector<int> > values;
};
#endif 


main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "Matrix.h"
int main() 
{

	srand(time(0));
	Matrix A(3,5);
	Matrix B(3,5);
	Matrix C(3,5);

	C = A+B;
	ofstream fout;
	
	fout.open("out.txt");
	A.print(fout);
	B.print(fout);
	C.print(fout);
	fout.close();
	return 0;
}


Matrix.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "Matrix.h"

Matrix::Matrix ()
{
	num_rows = 0;
	num_cols = 0;
}

// Put your code below:
Matrix::Matrix(int new_num_rows, int new_num_cols) {
    vector<vector<int> > values(new_num_rows, vector<int>(new_num_cols));
    for (int i = 0; i < new_num_rows; i++) {
        for (int j = 0; j < new_num_cols; j++) {
            int RANDNUM = rand() % 10;
            values[i][j] = RANDNUM;
        }
    }

    for (int i = 0; i < new_num_rows; i++) {
        for (int j = 0; j < new_num_cols; j++) {
            cout << values[i][j] << " ";
        }
        cout << "\n";
    }
}

Matrix Matrix::operator+(const Matrix& M2) const {
	if (num_rows != M2.num_rows || num_cols != M2.num_cols) {
		cout << "Dimensions don't match!" << endl;
	}
	else {
        Matrix new_mat(num_rows, num_cols);
        for (int i = 0; i < num_rows; i++) {
            for (int j = 0; j < num_cols; j++) {
                new_mat.values[i][j] = values[i][j] + M2.values[i][j];
            }
        }
        return new_mat;
	}
}
void Matrix::print(ofstream& fout) const {
    fout.open("Matrix.cpp");
}


I can only edit what comes under "Put your code below:" and nothing more. As you'll notice, what I have is almost useless. Any explanations on how to proceed would be much appreciated.
Last edited on Mar 11, 2020 at 6:54pm
Mar 10, 2020 at 2:56am
C_{jk} = A_{jk} + B_{jk}

¿would it be easier with apples?
say that instead of matrix, they are vectors
¿can you code C_j = A_j + B_j?
Mar 10, 2020 at 5:26pm
I don't understand the concept of matrices; the book I read and my teachers haven't explained it well...
Mar 10, 2020 at 5:38pm
How about "2D array" or "table"?

Lets take two matrices that each have two rows and three colums:
a b c
d e f

and
h k l
m n o

Their sum is a matrix that also has two rows and three colums:
a+h b+k c+l
d+m e+n f+o

Mar 10, 2020 at 6:18pm
I understand how matrices work in math (math major here :)) but I don't understand how they work in C++ specifically...
Mar 10, 2020 at 8:15pm
They don't. c++ is not aware of a 'matrix'. There are libraries (add ons to the language) that can do matrix math. If you are doing it yourself, you have to build some sort of container for the data and make it all happen yourself with loops and such. Is there a reason you are doing it yourself?

anyway,
addition is pretty simple.
double m1[3][5]; //this can be a 2-d vector, pointers, 1-d vector with home-made indexing, or various other storage approaches.
double * m1p = &m1[0][0]; //lets make this 1d because addition is a 1-d problem
double m2[3][5];
double * m2p = &m2[0][0];
double m3[3][5];
double * m3p = &m3[0][0];

..///omitting putting data in the matrices, but they need to be filled with data.

for(int i = 0; i<15; i++) //15 is 3*5 or rows*cols
m3p[i] = m1p[i]+m2p[i];

multiply isn't as easy to collapse to 1-d, of course.

vector<vector isn't collapsible to 1-d. You would have to iterate that twice.
for(r = 0; r < rows; r++)
for(c = 0; c< cols; c++) //sigh, unavoidable page faults and such.
result[r][c] = m1[r][c] + m2[r][c];

if you did it with a 1-d vector, though, you could.
to do that, you just index any 1-d container like this:
matrix[desired_row*number_columns+desired_column];
1-d indexing lets you transpose in place, reshape (eg turn a 10x10 into a 2x50), and do many other things without having to allocate more memory or make unnecessary copies, also lets you serialize easier, and more. I highly recommend it.
Last edited on Mar 10, 2020 at 8:21pm
Mar 10, 2020 at 9:13pm
Is there a reason you are doing it yourself?

Clearly homework and it states that the "backend storage" is:
vector<vector<int>> values;

Since everything is encapsulated into the class Matrix, one could choose row-major or column-major.

One can think the values as a list of rows. Each row is a vector<int> that has one int for each column.
"with loops and such":
1
2
3
4
5
for ( int r = 0; r < rows; ++r ) { // for each row
    for ( int c = 0; c < cols; ++c ) { // for each element on row r
        result[r][c] = m1[r][c] + m2[r][c];
    }
}

Note that the above requires that the result has rows elements and each of those "row" elements has cols integer elements.

EDIT: The sumMatrix in your code does not fulfill that requirement. I do suggest a different constructor of the std::vector.
Last edited on Mar 10, 2020 at 9:16pm
Mar 10, 2020 at 9:24pm
I've updated it above but I still have no idea what to do for void Matrix::print(ofstream& fout) const

In addition, the run of the code is not adding the matrices...

Also, why does the program give me the same set of random numbers for each matrix? Is there a way to give random integers to each matrix?

Last edited on Mar 10, 2020 at 9:28pm
Mar 10, 2020 at 9:52pm
1
2
Matrix::Matrix(int new_num_rows, int new_num_cols) {
    vector<vector<int> > values(new_num_rows, vector<int>(new_num_cols));

there you are creating a local variable `values', that happens to have the same name as your member variable `values'
so you are modifying the local variable, not your member.

use an initialization list instead
1
2
3
4
5
6
7
8
9
10
11
12
13
Matrix::Matrix(int new_num_rows, int new_num_cols): //<-- note the colon
//in the initialization list you may call the constructor of your variables
   values(new_num_rows, vector<int>(new_num_cols)), 
   num_rows(new_num_rows),
   num_cols(new_num_cols)
{//here starts the body of the constructor
    for (int i = 0; i < new_num_rows; i++) {
        for (int j = 0; j < new_num_cols; j++) {
            int RANDNUM = rand() % 10;
            values[i][j] = RANDNUM;
        }
    }
}


> the run of the code is not adding the matrices...
you never set any values for your matrices

> why does the program give me the same set of random numbers for each matrix?
srand() will seed the random number generator
for equal seeds you obtain the same sequence
you are calling srand() in your constructor
¿do you understand the problem?

> I still have no idea what to do for void Matrix::print(ofstream& fout) const
¿who wrote lines 21--26 of matrix.cpp? ¿what do those lines do?
¿what should your print() function do?
Last edited on Mar 10, 2020 at 9:52pm
Mar 10, 2020 at 10:51pm
I tried using your edited code, but the program doesn't output anything. I'm assuming that isn't a mistake.

I thought I set random values for the matrices

I get the idea of the issue but where should I call srand then?

The code on 21-26 adds spaces to the matrices... What code should I input within the void Matrix::print(ofstream& fout) const?

The print function is meant to output a Matrix object to a file as requested by the user
Last edited on Mar 10, 2020 at 11:07pm
Mar 10, 2020 at 11:31pm
What code would you use to print "regularly" to std::cout?
Mar 11, 2020 at 12:29am
No idea... The professor I have never really taught us well; that's actually why I need lots of help understanding some of the stuff, especially in relation to classes, headers, constructors, destructors, vectors and arrays...

Any chance you could explain and provide some sample code?
Mar 11, 2020 at 8:32am
I still haven't been able to figure out the code. Someone Help!! The work is due tomorrow and counts for my grade!
I'd really appreciate any and all help at this point.
Mar 11, 2020 at 6:25pm
This tutorial explains how you use std::cout to print information to the screen:

http://www.cplusplus.com/doc/tutorial/basic_io/
Mar 11, 2020 at 6:37pm
I understand how to use cout and so on, but what am I outputting? What exactly is the object?

Also, how am I meant to add the matrices when they have random numbers? The sum isn't working.

I'd really like a fix.
Mar 11, 2020 at 7:11pm
An "object" is an instance of a class. In this case, it's an instance of the Matrix class.

In yout main function, a, b, and c are all objects.
Mar 11, 2020 at 7:13pm
Ok... so I just have to cout Matrix then?

Also, any chance you could help fix the remainder of the code? I'm really struggling and as I mentioned, I need to upload this work in a couple of hours! Nobody - not even my professor - is willing to help...
Mar 11, 2020 at 7:17pm
copy your add routine.
change result = a+b to
cout << matrix[row][col]<< " " //inner loop
}
cout << endl; //outer loop.

so the inner loop runs across columns and prints
1 2 3 … //loop ends, print end of line
4 5 6 .. //etc
Last edited on Mar 11, 2020 at 7:18pm
Mar 11, 2020 at 7:21pm
What add routine? I hope you don't mean c=a+b because I can only change stuff in the matrix.cpp file and only below "Put your code below:"

Can you specify the specific line to change? Or write down the code with your implementations?

Also, is there any way to add the random numbers? My code simply generates a third matrix with random numbers instead of adding them (I think)
Last edited on Mar 11, 2020 at 7:24pm
Mar 11, 2020 at 8:48pm
line 42.
delete it.
copy lines 19-23 and put them there.
change cout to fout if that is what you want (unclear).

yes, you can add random numbers.
copy lines 19-23 and replace the print statements to place a random value into the matrix.

basically for a lot of this copy those loops or re-create them and change what the loop does to suit the task at hand.

This site has a tutorial on how to use <random> header. You can copy the example and use it to get a random value, and put that into your loop body (the 19-23 loop body again) to do that. You don't need the setup parts inside the loop, just the part that gets one random number .. lets do that:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// uniform_int_distribution
#include <iostream>
#include <random>

...   //setup a simple random series. 
  std::default_random_engine generator;
  std::uniform_int_distribution<int> distribution(0,10000); //put your range in here
//generator.seed (time(0)); //I think this is how to seed it to be different each execution.  or look up how to seed it if you want that feature.  


for (int i = 0; i < new_num_rows; i++) 
{
        for (int j = 0; j < new_num_cols; j++) 
       {         
            values[i][j] = distribution(generator) ;
        }
}



Last edited on Mar 11, 2020 at 8:55pm
Pages: 12