/* Program to demonstrate gaussian <strong class="highlight">elimination</strong>
on a set of linear simultaneous equations
*/
#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
const double eps = 1.e-15;
/*Preliminary pivoting strategy
Pivoting function
*/
double pivot(vector<vector<double> > &a, vector<double> &b, int i)
{
int n = a.size();
int j=i;
double t=0;
for(int k=i; k<n; k+=1)
{
double aki = fabs(a[k][i]);
if(aki>t)
{
t=aki;
j=k;
}
}
if(j>i)
{
double dummy;
for(int L=0; L<n; L+=1)
{
dummy = a[i][L];
a[i][L]= a[j][L];
a[j][L]= dummy;
}
double temp = b[j];
b[i]=b[j];
b[j]=temp;
}
return a[i][i];
}
/* Forward <strong class="highlight">elimination</strong> */
void triang(vector<vector<double> > &a, vector<double> &b)
{
int n = a.size();
for(int i=0; i<n-1; i+=1)
{
double diag = pivot(a,b,i);
if(fabs(diag)<eps)
{
cout<<"zero det"<<endl;
return;
}
for(int j=i+1; j<n; j+=1)
{
double mult = a[j][i]/diag;
for(int k = i+1; k<n; k+=1)
{
a[j][k]-=mult*a[i][k];
}
b[j]-=mult*b[i];
}
}
}
/*
DOT PRODUCT OF TWO VECTORS
*/
double dotProd(vector<double> &u, vector<double> &v, int k1,int k2)
{
double sum = 0;
for(int i = k1; i <= k2; i += 1)
{
sum += u[i] * v[i];
}
return sum;
}
/*
BACK SUBSTITUTION STEP
*/
void backSubst(vector<vector<double> > &a, vector<double> &b, vector<double> &x)
{
int n = a.size();
for(int i = n-1; i >= 0; i -= 1)
{
x[i] = (b[i] - dotProd(a[i], x, i + 1, n-1))/ a[i][i];
}
}
/*
REFINED GAUSSIAN <strong class="highlight">ELIMINATION</strong> PROCEDURE
*/
void gauss(vector<vector<double> > &a, vector<double> &b, vector<double> &x)
{
triang(a, b);
backSubst(a, b, x);
}
// EXAMPLE MAIN PROGRAM
int main()
{
int n;
cin >> n;
vector<vector<double> > a;
vector<double> x;
vector<double> b;
for (int i = 0; i < n; i++) {
vector<double> temp;
for (int j = 0; j < n; j++) {
int no;
cin >> no;
temp.push_back(no);
}
a.push_back(temp);
b.push_back(0);
x.push_back(0);
}
/*
for (int i = 0; i < n; i++) {
int no;
cin >> no;
b.push_back(no);
x.push_back(0);
}
*/
gauss(a, b, x);
for (size_t i = 0; i < x.size(); i++) {
cout << x[i] << endl;
}
return 0;
}
The above gaussian eleimination algorithm works fine on NxN matrices. But I need it to work on NxM matrix. Can anyone help me to do it? I am not very good at maths. I got this code on some website and i am stuck at it.
(optional) Understand this. Do some examples on paper.
Don't write code for Gaussian elimination yourself. Without some care, the naive gauss pivoting is unstable. You have to scale the lines and take care of pivoting with the greatest element, a starting point is there. Note that this advice holds for most linear algebra algorithms.
If you want to solve systems of equations, LU decomposition, QR decomposition (stabler than LU, but slower), Cholesky decomposition (in the case the system is symmetric) or SVD (in the case the system is not square) are almost always better choices. Gaussian elimination is best for computing determinants however.
Use the algorithms from LAPACK for the problems which need Gaussian elimination (eg. solving systems, or computing determinants). Really. Don't roll your own. Since you are doing C++, you may be interested in Armadillo which takes care of a lot of things for you.
If you must roll your own for pedagogical reasons, have a look first at Numerical Recipes, version 3. Version 2 can be found online for free if you're low on budget / have no access to a library.
As a general advice, don't code algorithms you don't understand.
You just cannot apply Gaussian elimination directly to an NxM problem. If you have more equations than unknowns, the your problem is over-determined and you have no solution, which means you need to use something like the least squares method. Say that you have A*x = b, then instead of having x = inv(A)*b (when N=M), then you have to do x = inv(A^T*A)*A^T*b.
In the case where you have less equations then unknowns, then your problem is underdetermined and you have an infinity of solutions. In that case, you either pick one at random (e.g. setting some of the unknowns to an arbitrary value), or you need to use regularization, which means trying adding some extra constraints.
You can apply echelon reduction, like in this snippet
#include <iostream>
#include <algorithm>
#include <vector>
#include <iomanip>
using namespace std;
/*
A rectangular matrix is in echelon form(or row echelon form) if it has the following
three properties :
1. All nonzero rows are above any rows of all zeros.
2. Each leading entry of a row is in a column to the right of the leading entry of
the row above it.
3. All entries in a column below a leading entry are zeros.
If a matrix in echelon form satisfies the following additional conditions,
then it is in reduced echelon form(or reduced row echelon form) :
4. The leading entry in each nonzero row is 1.
5. Each leading 1 is the only nonzero entry in its column.
*/
template <typename C> void print(const C& c) {
for (const auto& e : c) {
cout << setw(10) << right << e;
}
cout << endl;
}
template <typename C> void print2(const C& c) {
for (const auto& e : c) {
print(e);
}
cout << endl;
}
// input matrix consists of rows, which are vectors of double
vector<vector<double>> Gauss::Reduce(const vector<vector<double>>& matrix)
{
if (matrix.size() == 0)
throw string("Empty matrix");
auto A{ matrix };
auto mima = minmax_element(A.begin(), A.end(), [](const vector<double>& a, const vector<double>& b) {return a.size() < b.size(); });
auto mi = mima.first - A.begin(), ma = mima.second - A.begin();
if (A[mi].size() != A[ma].size())
throw string("All rows shall have equal length");
size_t height = A.size();
size_t width = A[0].size();
if (width == 0)
throw string("Only empty rows");
for (size_t row = 0; row != height; row++) {
cout << "processing row " << row << endl;
// Search for maximum below current row in column row and move it to current row; skip this step on the last one
size_t col{ row }, maxRow{ 0 };
// find pivot for current row (partial pivoting)
while (col < width)
{
maxRow = distance(A.begin(), max_element(A.begin() + row, A.end(), [col](const vector<double>& rowVectorA, const vector<double>& rowVectorB) {return abs(rowVectorA[col]) < abs(rowVectorB[col]); }));
if (A[maxRow][col] != 0) // nonzero in this row and column or below found
break;
++col;
}
if (col == width) // e.g. in current row and below all entries are zero
break;
if (row != maxRow)
{
swap(A[row], A[maxRow]);
cout << "swapped " << row << " and " << maxRow;
}
cout << " => leading entry in column " << col << endl;
print2(A);
// here col >= row holds; col is the column of the leading entry e.g. first nonzero column in current row
// moreover, all entries to the left and below are zeroed
if (row+1 < height)
cout << "processing column " << col << endl;
// Make in all rows below this one 0 in current column
for (size_t rowBelow = row + 1; rowBelow < height; rowBelow++) {
// subtract product of current row by factor
double factor = A[rowBelow][col] / A[row][col];
cout << "processing row " << rowBelow << " below the current; factor is " << factor << endl;
if (factor == 0)
continue;
for (size_t colRight{ col }; colRight < width; colRight++)
{
auto d = A[rowBelow][colRight] - factor * A[row][colRight];
A[rowBelow][colRight] = abs(d) < DBL_EPSILON ? 0 : d;
}
print(A[rowBelow]);
}
}
// the matrix A is in echelon form now
cout << "matrix in echelon form" << endl;
print2(A);
// reduced echelon form follows (backward phase)
size_t row(height-1);
auto findPivot = [&row, A] () -> size_t {
do
{
auto pos = find_if(A[row].begin(), A[row].end(), [](double d) {return d != 0; });
if (pos != A[row].end())
return pos - A[row].begin();
} while (row-- > 0);
return A[0].size();
};
do
{
auto col = findPivot();
if (col == width)
break;
cout << "processing row " << row << endl;
if (A[row][col] != 1)
{
//scale row row to make element at [row][col] equal one
auto f = 1 / A[row][col];
transform(A[row].begin()+col, A[row].end(), A[row].begin()+col, [f](double d) {return d * f; });
}
auto rowAbove{ row};
while (rowAbove > 0)
{
rowAbove--;
double factor = A[rowAbove][col];
if (abs(factor) > 0)
{
for (auto colAbove{ 0 }; colAbove < width; colAbove++)
{
auto d = A[rowAbove][colAbove] - factor * A[row][colAbove];
A[rowAbove][colAbove] = abs(d) < DBL_EPSILON ? 0 : d;
}
cout << "transformed row " << rowAbove << endl;
print(A[rowAbove]);
}
}
} while (row-- > 0);
return A;
}
Related
For the past few hours I have been trying to build a C++ module that, upon requesting the input of the user on the size and contents of 2 matrices (restricted to ones that can be multiplied together), then proceeds to multiply them together and return the values of a third answer matrix. While the matrix input commands seem to work based on thorough testing, I can't seem to get a correct answer from my multiplication command, despite going through each step of the algorithm and how it corresponds to actual matrix multiplication. The first value of the answer matrix is correct, and then all succeeding values are incorrect by some factor. Does anyone have any insight as to what could be going wrong?
#include <iostream>
#include <cmath>
using namespace std;
int r, c, a1, a2, b1, b2; //defines row and column indices
double m[1][1], m2[1][1], a[1][1]; //initializes matrices
double b;
int inflag = true;
int repflag = false;
void defmatrix() { //Defines the matrix size of the first inputted matrix
cout << "Matrix Rows: ";
cin >> r;
cout << "Matrix Columns: ";
cin >> c;
}
void fillmatrix() { //Fills the matrix with automatic or user-inputted values
if (inflag == true) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cout << "Number in row " << i + 1 << " and column " << j + 1 << ": ";
cin >> b;
m[i][j] = b;
}
}
} else {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
m[i][j] = 1;
}
}
}
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cout << m[i][j] << " ";
}
}
}
void matrixmult() { //Multiplication function for matrix math
if (repflag == false) {
cout << "\n" << "Your second matrix will have " << c << " rows" << "\n";
b1 = c;
a1 = r;
r = c;
cout << "Second matrix columns: ";
cin >> c;
a2 = c;
double m2[r][c] = {};
if (inflag == true) {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cout << "Number in row " << i + 1 << " and column " << j + 1 << ": ";
cin >> b;
m2[i][j] = b;
}
}
} else {
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
m2[i][j] = 1;
}
}
}
a[a1][a2];
for (int i = 0; i < a1; i++) {
for (int j = 0; j < a2; j++) {
b = 0;
for (int d = 0; d < b1; d++) {
b = b + (m[i][d] * m2[d][j]);
}
a[i][j] = b;
}
}
for (int i = 0; i < a1; i++) {
for (int j = 0; j < a2; j++) {
cout << a[i][j] << " ";
}
}
}
}
int main() { //main file
defmatrix();
double m[r][c] = {};
fillmatrix();
matrixmult();
}
Thanks in advance!
There is a problem in almost every line. It is easier to point out the good parts. The central for loop that calculates the matrix product seems OK. Most everything else needs to be thrown out and rewritten. This includes all declarations and all function interfaces.
Here's how I would start writing the program.
int main()
{
int rows;
int cols;
int common_size; // columns in the matrix A and rows in the matrix B
std::cout << "Enter number of rows in the result : ";
std::cin >> rows;
std::cout << "Enter number of columns in the result : ";
std::cin >> cols;
std::cout << "Enter the common size : ";
std::cin >> common_size;
Now we need to declare the matrices, but here comes a problem. One would naïvely want to write something like
int a[rows][common_size], b[common_size][cols], c[rows][cols];
but alas, this is not legal C++. This declaration may work with your compiler, or it may not. There are several ways to declare the matrices correctly. The simplest one is to reserve a fixed amount of memory for each one, and just use a portion:
int a[10][10], b[10][10], c[10][10];
Naturally you need to check that the sizes provided by the user do not exceed 10.
Another method is to use the C++ version of variable length array, called [vector]. The declaration of a will look something like this:
std::vector<std::vector<int>> a(rows, std::vector<int>(common_size));
With the second method, there is no real limitation on the matrix sizes.
Neither method is adequate for any real software, but they are enough to complete your C++ exercise. Real software uses more advanced C++ concepts like classes to define matrices. Just something to be aware of.
I will not continue writing it at the same level of detail. This is your task. I will just show what the rest of main could look like.
input_matrix(a, rows, common_size);
input_matrix(b, common_size, cols);
multiply_matrices(a, b, c, rows, common_size, cols);
print_matrix(c, rows, cols);
Note function calls using arguments. Implement these functions, and you are good to go. Note, if you choose vectors, you will need to pass some arguments by reference. In this case you could also write the functions this way:
input_matrix(a);
input_matrix(b);
c = multiply_matrices(a, b);
print_matrix(c);
but this is a talk for another day.
Although you're asking to find mistakes in your code, as your task is interesting I decided to implement my own solution from scratch for you. Even if it is unacceptable answer, still it might be useful for educational purpose.
I made code in a form of class Matrix that supports multiplication operation between two matching matrices like A *= B;. As you did, I also implemented two methods .Input() and .Output() that correspondingly read matrix from std::cin and output to std::cout.
As a bonus there is also a method .At(i, j) that returns reference to element of a matrix with bounds checking, similar to std::vector.
Sure class can be extended to many other matrices operations (like addition A += B; or subtraction A -= B;), but I limited my class to only those things that you used in your original code.
To do what you wanted using my class is simple as few lines of code (that are located further in main() function of following code snippet):
Matrix A, B;
A.Input(); B.Input();
A *= B;
A.Output();
Full code:
Try it online!
#include <stdexcept>
#include <vector>
#include <sstream>
#include <iomanip>
#include <iostream>
#define ASSERT_MSG(cond, msg) { if (!(cond)) throw std::runtime_error("Assertion (" #cond ") failed at line " + std::to_string(__LINE__) + "! Msg: '" + std::string(msg) + "'."); }
#define ASSERT(cond) ASSERT_MSG(cond, "")
class Matrix {
public:
using FloatT = double;
Matrix(size_t rows = 0, size_t cols = 0)
: rows_(rows), cols_(cols) {
Clear();
}
Matrix & Clear() {
m_.clear();
m_.resize(rows_ * cols_);
return *this;
}
size_t Rows() const { return rows_; }
size_t Cols() const { return cols_; }
Matrix & operator = (Matrix && other) {
rows_ = other.rows_;
cols_ = other.cols_;
m_ = std::move(other.m_);
other.rows_ = 0;
other.cols_ = 0;
return *this;
}
FloatT & operator() (size_t i, size_t j) {
return m_[i * cols_ + j];
}
FloatT const & operator() (size_t i, size_t j) const {
return const_cast<Matrix &>(*this)(i, j);
}
FloatT & At(size_t i, size_t j) {
ASSERT_MSG(i < rows_ && j < cols_,
"Matrix index (" + std::to_string(i) + ", " + std::to_string(j) +
") out of bounds (" + std::to_string(rows_) + ", " + std::to_string(cols_) + ")!");
return (*this)(i, j);
}
FloatT const & At(size_t i, size_t j) const {
return const_cast<Matrix &>(*this).At(i, j);
}
Matrix & operator *= (Matrix const & B) {
Matrix const & A = *this;
ASSERT_MSG(A.Cols() == B.Rows(),
"Number of A.Cols " + std::to_string(A.Cols()) +
" and B.Rows " + std::to_string(B.Rows()) + " don't match!");
Matrix C(A.Rows(), B.Cols());
for (size_t i = 0; i < A.Rows(); ++i)
for (size_t j = 0; j < B.Cols(); ++j) {
FloatT sum = 0;
for (size_t k = 0; k < A.Cols(); ++k)
sum += A(i, k) * B(k, j);
C(i, j) = sum;
}
*this = std::move(C);
return *this;
}
Matrix & Input() {
std::cout << "Enter number of rows and columns: ";
std::cin >> rows_ >> cols_;
Clear();
std::cout << "Enter all matrix elements:" << std::endl;
for (size_t i = 0; i < rows_; ++i)
for (size_t j = 0; j < cols_; ++j)
std::cin >> (*this)(i, j);
return *this;
}
Matrix const & Output(size_t precision = 6) const {
std::vector<std::vector<std::string>> cells(Rows(),
std::vector<std::string>(Cols()));
std::ostringstream ss;
size_t max_len = 0;
for (size_t i = 0; i < Rows(); ++i)
for (size_t j = 0; j < Cols(); ++j) {
ss.str("");
ss << std::fixed << std::setprecision(precision)
<< (*this)(i, j);
cells[i][j] = ss.str();
max_len = std::max(max_len, cells[i][j].size());
}
for (auto const & row: cells) {
for (auto const & cell: row)
std::cout << std::string(max_len - cell.size() + 1, ' ')
<< cell;
std::cout << std::endl;
}
return *this;
}
private:
size_t rows_ = 0, cols_ = 0;
std::vector<FloatT> m_;
};
int main() {
try {
Matrix A, B;
A.Input();
B.Input();
A *= B;
A.Output();
return 0;
} catch (std::exception const & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
}
Input:
Enter number of rows and columns: 3 2
Enter all matrix elements:
1.01 2.02
3.03 4.04
5.05 6.06
Enter number of rows and columns: 2 4
Enter all matrix elements:
7.07 8.08 9.09 10.10
11.11 12.12 13.13 14.14
Output:
29.582900 32.643200 35.703500 38.763800
66.306500 73.447200 80.587900 87.728600
103.030100 114.251200 125.472300 136.693400
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
So I got my Data structures and algorithms project. I basically need to develop a class Matrix with following atributes:
list<list<pair<int,double>>>, (In which are only non-zero elements of a Matrix. Value of a certain element is stored as the second argument of a pair, and the first argument of a pair represents an actual column in which that element is located in the original Matrix)
vector< int> rows, (rows[i] - Represents an actual row for each list in a list of lists above, respectively)
Actual number of rows,
Actual number of columns.
In my project so far I have developed specific constructors, adding and substracting matrices etc. The only thing that I am not able to do is multiply two instances of a class Matrix, meaning I am not able to develop an operator* for class Matrix.
Explanation of the problem:
Assuming I have the following two instances of class Matrix:
Instance A:
list<list<pair<int,double>>>: {{{10,5},{40,15}},{{50,25}},{{80,35}}}
vector<int>: {2,10,70};
actual number of rows: 100
actual number of columns: 100
Instance B:
list<list<pair<int,double>>>: {{{1,6},{2,5},{3,7}},{{3,4}},{{80,1}}}
vector<int>: {1,2,33};
actual number of rows: 100
actual number of columns: 100
Obviously multiplication is defined for these matrices since the number of columns of matrix A is equal to the number of rows of matrix B.
I am having trouble with finding the correct algorithm for multiplying these matrices.
Can somebody write in short lines what could be one of the algorithms for multiplying these.
The main idea consists in having convenient primitive to set/get the value at position (i, j) of a matrix, its number of rows and its number of column.
For sake of simplicity, I replaced in the following code your top list by a vector (it's more efficient as you have random access to the i-th value):
#include <cassert>
#include <iostream>
#include <list>
#include <vector>
using namespace std;
class Matrix {
private:
vector<list<pair<unsigned, double>>> data;
unsigned m;
unsigned n;
public:
Matrix(unsigned m, unsigned n):
m(m),
n(n),
data(m)
{}
inline unsigned num_rows() const {
return m;
}
inline unsigned num_columns() const {
return n;
}
double get(unsigned i, unsigned j) const {
for (pair<unsigned, double> p : data[i]) {
if (p.first == j) return p.second;
}
return 0.0;
}
void set(unsigned i, unsigned j, double v) {
for (pair<unsigned, double> p : data[i]) {
if (p.first == j) {
p.second = v;
return;
}
}
if (v) {
data[i].push_back(make_pair(j, v));
}
}
};
Matrix operator * (const Matrix & a, const Matrix & b) {
unsigned m = a.num_rows(),
n = b.num_columns(),
k_max = a.num_columns();
assert (a.num_columns() == b.num_rows());
Matrix c(m, n);
for (unsigned i = 0; i < m; i++) {
for (unsigned j = 0; j < n; j++) {
double value = 0;
for (unsigned k = 0; k < k_max; k++) {
value += a.get(i, k) * b.get(k, j);
}
if (value) c.set(i, j, value);
}
}
return c;
}
ostream & operator << (ostream & out, const Matrix & a) {
for (unsigned i = 0; i < a.num_rows(); i++) {
for (unsigned j = 0; j < a.num_columns(); j++) {
out << a.get(i, j) << "\t";
}
out << endl;
}
return out;
}
int main() {
Matrix a(2, 3), b(3, 1);
for (unsigned i = 0; i < a.num_rows(); i++) {
for (unsigned j = 0; j < a.num_columns(); j++) {
a.set(i, j, 10 * i + j);
}
}
for (unsigned i = 0; i < b.num_rows(); i++) {
for (unsigned j = 0; j < b.num_columns(); j++) {
b.set(i, j, 10 * (i + 1));
}
}
Matrix c = a * b;
cout << "a:" << endl << a << endl
<< "b:" << endl << b << endl
<< "c:" << endl << c << endl
;
return 0;
}
Result:
a:
0 1 2
10 11 12
b:
10
20
30
c:
80
680
My implementation of the Durand-Kerner-Method (https://en.wikipedia.org/wiki/Durand%E2%80%93Kerner_method) does not seem to work. I believe (see following code) that I am not calculating new approximation correctly in the algorithm part itself. I cannot seem to be able to fix the problem. Very grateful for any advice.
#include <complex>
#include <cmath>
#include <vector>
#include <iostream>
#include "DurandKernerWeierstrass.h"
using namespace std;
using Complex = complex<double>;
using vec = vector<Complex>;
using Matrix = vector<vector<Complex>>;
//PRE: Recieves input value of polynomial, degree and coefficients
//POST: Outputs y(x) value
Complex Polynomial(vec Z, int n, Complex x) {
Complex y = pow(x, n);
for (int i = 0; i < n; i++){
y += Z[i] * pow(x, (n - i - 1));
}
return y;
}
/*PRE: Takes a test value, degree of polynomial, vector of coefficients and the desired
precision of polynomial roots to calculate the roots*/
//POST: Outputs the roots of Polynomial
Matrix roots(vec Z, int n, int iterations, const double precision) {
Complex z = Complex(0.4, 0.9);
Matrix P(iterations, vec(n, 0));
Complex w;
//Creating Matrix with initial starting values
for (int i = 0; i < n; i++) {
P[0][i] = pow(z, i);
}
//Durand Kerner Algorithm
for (int col = 0; col < iterations; col++) {
*//I believe this is the point where everything is going wrong*
for (int row = 0; row < n; row++) {
Complex g = Polynomial(Z, n, P[col][row]);
for (int k = 0; k < n; k++) {
if (k != row) {
g = g / (P[col][row] - P[col][k]);
}
}
P[col][row] -= g;
}
return P;
}
}
The following Code is the code I am using to test the function:
int main() {
//Initializing section
vec A = {1, -3, 3,-5 };
int n = 3;
int iterations = 10;
const double precision = 1.0e-10;
Matrix p = roots(A, n, iterations,precision);
for (int i = 0; i < iterations; i++) {
for (int j = 0; j < n; j++) {
cout << "p[" << i << "][" << j << "] = " << p[i][j] << " ";
}
cout << endl;
}
return 0;
}
Important to note the Durand-Kerner-Algorithm is connected to a header file which is not included in this code.
Your problem is that you do not transcribe the new values into the next data record with index col+1. Thus in the next loop you start again with a data set of zero entries. Change to
P[col+1][row] = P[col][row] - g;
If you want to use the new improved approximation immediately for all following approximations, then use
P[col+1][row] = (P[col][row] -= g);
Then the data sets all contain the next approximations, especially the first one will no longer contain the initially set powers.
I want to distribute numbers by a certain percentage randomly within a matrix.For example I have a matrix 150*150 and I want to Fill out with 0,1,2
randomly with percentage like this 10% for 0 30% for 2 and 60% for 1.What should I do.actually I did something but without percentage but it didn't work perfectly.
for (int i = 0; i < 151 i++) {
for (int j = 0; j <151; j++) {
if (random(100) < 10) {
Array(i, j) = 1;
}
if (random(50) < 10) {
Array(i, j) = 2;
}
}
}
Since C++11, the Standard Library provides the function std::discrete_distribution, defined in header <random>, which
produces random integers on the interval [0, n), where the probability of each individual integer i is defined as w
i/S, that is the weight of the ith integer divided by the sum of all n weights.
Given OP's percentages:
std::discrete_distribution<int> d({10, 60, 30});
HERE, a testable code snippet.
I'm quite sure that this is not the most efficient way to approach this problem and my beginner c++ code should never be used as it's, but still if you want a reference, this is how i did it :
#include <iostream>
#include <random>
#include <tuple>
#include <vector>
#define ROWS 5
#define COLS 5
using tuple = std::tuple<int, int>;
const int Percentage(const int value)
{
const int percent = std::round((value / 100.0) * (ROWS * COLS));
std::cout << value << "% of " << ROWS * COLS << " : " << percent << std::endl;
return percent;
}
const int RandomIndex(const int& size)
{
std::mt19937 range;
range.seed(std::random_device()());
std::uniform_int_distribution<std::mt19937::result_type> dist(0, size);
return dist(range);
}
void FillMatrix(int matr[][COLS], std::vector<tuple>& num)
{
// holds the numbers, from which a random number
// will be stored to the matrix
std::vector<int> fillers;
// holds the random index among the fillers
uint8_t random_index;
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
/*
* check if the count of a particular number to be added to
* the matrix is zero or not.
* if zero : then dont append to filler vector
* else : append to filler vector
*/
for (tuple item : num) {
if (std::get<1>(item) != 0) {
fillers.emplace_back(std::get<0>(item));
}
}
// get the index of a random item in fillers vector
random_index = RandomIndex(fillers.size() - 1);
// insert this random element to matrix
matr[i][j] = fillers[random_index];
/*
* find the percentage value(or count) of the number
* corresponding to the random number and decrement it
* so as to denote that it has been used.
*/
for (tuple& item : num) {
if (std::get<0>(item) == fillers[random_index]) {
std::get<1>(item) -= 1;
}
}
// clear the current fillers vector
fillers.clear();
}
}
}
int main()
{
int matrix[ROWS][COLS];
// each tuple has a number and it's corresponding percentage
std::vector<tuple> numbers = {tuple(0, Percentage(10)),
tuple(1, Percentage(30)),
tuple(2, Percentage(60))};
// fill the matrix with values provided in the vector
FillMatrix(matrix, numbers);
// print the matrix
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
std::cout << matrix[i][j] << "\t";
}
std::cout << "\n";
}
return 0;
}
define ROWS and COLS as 150 in your case.
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
#include<iomanip>
using namespace std;
typedef pair<int, int> intPair;// rename intPair
typedef vector<double> doubleVector; //rename doubleVetcor
typedef vector<intPair> intPairVector; // rename intPairVector
// Union-Find Disjoint Sets Library written in OOP manner, using both path compression and union by rank heuristics
class UnionFind { // OOP style
private:
doubleVector p, rank, setSize; // remember: vi is vector<double>
int numSets;
public:
UnionFind(int N) {
setSize.assign(N, 1);
numSets = N;
rank.assign(N, 0);
p.assign(N, 0);
for (int i = 0; i < N; i++)
p[i] = i;
}
int findSet(int i) {
return (p[i] == i) ? i : (p[i] = findSet(p[i]));
}
bool isSameSet(int i, int j) {
return findSet(i) == findSet(j);
}
void unionSet(int i, int j) {
if (!isSameSet(i, j)) {
numSets--;
int x = findSet(i), y = findSet(j);
// rank is used to keep the tree short
if (rank[x] > rank[y]) {
p[y] = x;
setSize[x] += setSize[y];
}
else{
p[x] = y;
setSize[y] += setSize[x];
if (rank[x] == rank[y])
rank[y]++;
}
}
}
int numDisjointSets() {
return numSets;
}
int sizeOfSet(int i) {
return setSize[findSet(i)];
}
};
vector<intPairVector> AdjList;
int main() {
int num_verts=0;
cin >> num_verts;
//Pre-allocate a vector of num_verts rows, each of which is a vector
//of num_verts copies of 0.0
vector<vector<double>> matrix(num_verts, vector<double>(num_verts,0.0));
//Requires c++11 or higher
for(int row = 0; row<num_verts;++row) {
for(int col = 0; col<num_verts; ++col){
cin >> matrix[row][col];
}
}
//print out the matrix we just read
for(int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
cout << setprecision(2) << fixed << matrix[row][col] << "\t";
}
cout << "\n";
}
// Kruskal's algorithm merged
AdjList.assign(num_verts, intPairVector());
vector< pair<double, intPair> > EdgeList; // (weight, two vertices) of the edge
for (int row = 0; row<num_verts; ++row) {
for(int col=0; col<num_verts;++col){
EdgeList.push_back(make_pair(matrix[row][col], intPair(row,col)));
AdjList[row].push_back(intPair(row,matrix[row][col]));
AdjList[col].push_back(intPair(col,matrix[row][col]));
}
}
sort(EdgeList.begin(), EdgeList.end()); // sort by edge weight O(E log E)
// note: pair object has built-in comparison function
double mst_cost = 0.0;
UnionFind UF(num_verts); // all V are disjoint sets initially
for (int i = 0; i < num_verts*num_verts; i++) { // for each edge, O(E)
pair<double,intPair> front = EdgeList[i];
if (!UF.isSameSet(front.second.first, front.second.second)) { // check
mst_cost += front.first; // add the weight of e to MST
UF.unionSet(front.second.first, front.second.second); // link them
}
} // note: the runtime cost of UFDS is very light
//display the weight of the MST
cout << setprecision(2) << fixed << mst_cost << endl;
return 0;
}
I am trying to display the minimum spanning tree from this code, I cannot figure out how to get this code to display the modified matrix. The code is working correctly, by that I mean it is compiling and calculating the correct weight for the graph. However, I am unsure how to display the minimum spanning tree from using Kruskals algorithm. Thanks for any help
Whenever you add the weight of an edge to the weight of the MST, you should also add that edge to a list to keep track of the MST edges.