MathMatrix Echelon

A.Third Edition
This is the 3.5 edition of my MathMatrix class and I corrected a big bug of its echelon method. And add a so-called
LHRRCC method which is abbreviation of "Linear Homogeneous Recursive Relation with Constant Coefficient". 
B.Idea of program
1¡£ Basic idea: 
The echelon method actually can solve system functions. LHRRCC is like a joke. Do you know discrete mathematics?
2¡£ Program design: 
The only problem with echelon is that when the diagonal entry is 0, you have to go to next row but remain same
column to make it 1, and after you come down to last row, if your column parameter doesnot reach the minimum of 
both row and column, you have to go over. 
3¡£ Major function:
A.  void MathMatrix::echelon(int r, int c, bool reduced)
Reduced means whether making all entries above diagonal 0's. 
B. Matrix& LogicMatrix::warshall()
Warshall algorithm is such simple, but not so easy to understand. 
4¡£ Further improvement£º	
¡¡
#include <iostream>
#include <cmath>
#include <fstream>

using namespace std;

const int MaxRow = 10;
const int MaxCol = 10;
const double LIMIT = 0.01;


class Matrix
{
private:
	int rowNum;
	int colNum;
	double lst[MaxRow][MaxCol];
protected:
	void mul(int dest, double scalor);
	void mul(int source, int dest, double scalor);
public:
	Matrix();
	int row() const {return rowNum;}
	int col() const {return colNum;}
	void setRow(const int newRow) { rowNum = newRow;}
	void setCol(const int newCol) { colNum = newCol;}
	void display();
	double& items(int r, int c);
	void initialize();
	void readFromFile(const char* fileName);
	Matrix& operator = (Matrix other);
	Matrix& transposition();	
};

class MathMatrix: public Matrix
{
public:
	void echelon(int r, int c, bool reduced=true);
	//Linear Homogeneous Recurrsive Relation with Constant Coefficients
	void LHRRCC(double* roots, double* initials, int degree);
	Matrix& operator+(Matrix other);
	Matrix& operator *(double i);
	Matrix& operator *(Matrix otherMatrix);  
};

class LogicMatrix: public Matrix
{
protected:
	
public:
	Matrix& operator &&(Matrix otherMatrix);
	Matrix& operator ||(Matrix otherMatrix);
	Matrix& power(int exponent);
	bool reflexive();
	bool symmetric();
	bool antiSymmetric();
	bool transitive();
	bool equivalent();
	bool partialOrder();
	Matrix& transitiveClosure();
	Matrix& reflexiveClosure();
	Matrix& symmetricClosure();
	Matrix& warshall();
};


int main()
{
	MathMatrix M;
	M.readFromFile("c:\\nick.txt");
	M.display();
	M.echelon(0,0);
	M.display();
	/*
	double roots[2] = {2,-1};
	double initials[2] = {2,7};
	MathMatrix M;
	M.LHRRCC(roots, initials, 2);
	M.display();
	M.echelon(0,0);
	
	M.display();
	*/
	return 0;
}
Matrix& LogicMatrix::warshall()
{
	int n = row(); //n is dimention of matrix
	for (int k=0; k<n; k++)
	{
		for (int r=0;r<n; r++)
		{
			for (int c=0; c<n; c++)
			{
				items(r,c) = items(r,c)|| items(r,k) && items(k,c);
			}
		}
	}
	return *this;
}


Matrix& LogicMatrix::symmetricClosure()
{
	for (int r=0; r< row(); r++)
	{
		for (int c=0; c< col(); c++)
		{
			if (items(r,c)==1)
			{
				items(c, r) = 1;
			}
		}
	}
	return *this;
}

Matrix& LogicMatrix::reflexiveClosure()
{
	for (int i=0; i<row(); i++)
	{
		items(i, i) = 1;
	}
	return *this;
}


bool LogicMatrix::partialOrder()
{
	return reflexive()&&antiSymmetric()&&transitive();
}


bool LogicMatrix::equivalent()
{
	return reflexive()&&symmetric()&&transitive();
}


Matrix& LogicMatrix::transitiveClosure()
{
	int dim = col();
	LogicMatrix N;
	N = *this;
	for (int i = 1; i<=dim; i++)
	{
		(Matrix)N = (Matrix)(N ||power(i));
	}
	*this = N;
	return *this;
}


Matrix& LogicMatrix::operator ||(Matrix otherMatrix)
{
	int dim = col();
	for (int r = 0; r< dim; r++)
	{
		for (int c=0; c< dim; c++)
		{
			items(r,c) = (int)items(r,c) ||(int)otherMatrix.items(r, c);
		}
	}
	return *this;
}


bool LogicMatrix::reflexive()
{
	bool result = true;
	for (int i =0; i<col(); i++)
	{
		result = result&&items(i, i);
	}
	return result;
}

bool LogicMatrix::symmetric()
{
	int dim = col();  //since the function will be called nxn times, better use variable.
	for (int r = 0; r< dim; r++)
	{
		for (int c = r; c< dim; c++)
		{			
			if ((int)items(r,c)^(int)items(c,r))//exclusive or
			{
				return false;
			}
		}
	}
	return true;
}

bool LogicMatrix::antiSymmetric()
{
	int dim = col();
	for (int r =0; r< dim; r++)
	{
		for (int c = r; c< dim; c++)
		{
			if (items(r,c)&&items(c,r))
			{
				if (r != c)
				{
					return false;
				}
			}
		}
	}
	return true;
}

bool LogicMatrix::transitive()
{
	int dim = col();
	for (int r =0; r< dim; r++)
	{
		for (int c=0; c< dim; c++)
		{
			if (items(r,c))//if find an entry which is 1's
			{
				for (int i =0; i< dim; i++) // try to find in c'th row 
				{
					if (items(c, i))
					{
						if (!items(r, i))
						{
							return false;
						}
					}
				}
			}
		}
	}
	return true;
}

Matrix& LogicMatrix::operator &&(Matrix otherMatrix)
{
	bool dummy=false;
	int dim = col();  //as this function is used so many times, better use variable, 
	for (int r =0; r<dim; r++)
	{
		for (int c =0; c<dim; c++)
		{
			for (int i=0; i<dim; i++)
			{
				dummy = dummy||(items(r,i)&&otherMatrix.items(i, c));
			}
			items(r, c) = dummy;
			dummy = false;
		}
	}
	return *this;
}

Matrix& LogicMatrix::power(int exponent)
{
	Matrix N;
	N = *this; //I have to copy a temp Matrix to keep original one
	for (int i=1; i<exponent; i++)
	{
		this->operator &&(N);
	}
	return (*this);
}

Matrix& Matrix::transposition()
{
	double hold;
	int temp;
	for (int r =0; r< rowNum; r++)
	{
		for (int c=0; c< r; c++)
		{
			hold = lst[r][c];
			lst[r][c] = lst[c][r];
			lst[c][r] = hold;
		}
	}
	temp = rowNum;
	rowNum = colNum;
	colNum = temp;
	return (*this);
}


void MathMatrix::LHRRCC(double *roots, double* initials, int degree)
{
	for (int r=0; r<degree; r++)
	{
		for (int c=0;c<degree; c++)
		{
			if (r==0)
			{
				items(r,c) = 1;
			}
			else
			{
				items(r,c) = items(r-1,c)*roots[c];
			}
		}
		items(r,c) = initials[r];
	}
	setRow(degree);
	setCol(degree+1);
}

Matrix& MathMatrix::operator +(Matrix other)
{
	if (row()!= other.row() || col()!= other.col())
	{
		cout<<"\nTwo matrix has different row or col number!\n";
		return (*this);
	}
	else
	{
		for (int r=0; r< row(); r++)
		{
			for (int c=0; c< col(); c++)
			{
				items(r, c) +=other.items(r, c);
			}
		}
		return (*this);
	}
}

Matrix& MathMatrix::operator *(Matrix other)
{
	double total =0;
	Matrix temp;
	temp.setRow(row());
	temp.setCol(other.col());

	if (col()!=other.row())
	{
		cout<<"\nrow & col are not same!\n";
	
	}
	else
	{
		for (int r =0; r< row(); r++)
		{
			for (int c=0; c<other.col(); c++)
			{
				total =0;
				for (int i=0; i<col(); i++)
				{
					total += items(r,i) * other.items(i, c);
				}
				temp.items(r, c) = total;
			}
		}
		(Matrix)(*this) = temp;
	
	}
	return (*this);
}
				
Matrix& Matrix::operator =(Matrix other)
{
	setRow(other.row());
	setCol(other.col());
	for (int r=0; r< other.row(); r++)
	{
		for (int c=0; c< other.col(); c++)
		{
			lst[r][c] = other.items(r, c);
		}
	}
	
	return (*this);
}

void Matrix::mul(int dest, double scalor)
{
	for (int c=0; c< colNum; c++)
	{
		lst[dest][c] *= scalor;
	}
}

Matrix& MathMatrix::operator *(double i)
{
	for (int r=0; r<row(); r++)
	{
		for (int c=0; c<col(); c++)
		{
			items(r, c) *= i;
		}
	}
	return (*this);
}

void MathMatrix::echelon(int r, int c, bool reduced)
{
	if (r<row()&&c<col()&&c<row())
	{
		if (items(r, c) !=0)
		{
			mul(r, 1/items(r,c));   //make it 1 for this row
			for (int i=(!reduced?r+1:0); i< row(); i++)
			{
				if (i!=r)
				{
					mul(r, i, -items(i,c));
				}
			}	
			echelon(r+1, c+1, reduced);
		}
		else
		{
			echelon(r+1, c, reduced);
		}
	}
	else
	{
		if (c<row()&&c<col())
		{
			echelon(0, c, reduced);
		}
	}
}

void Matrix::mul(int source, int dest, double scalor)
{
	for (int c=0; c< colNum; c++)
	{
		lst[dest][c] += lst[source][c]*scalor;
	}
}


double& Matrix::items(int r, int c)
{
	return lst[r][c];
}

void Matrix::readFromFile(const char* fileName)
{
	int r=0, c=0;
	char ch;
	ifstream f;
	f.open(fileName);
	while (!f.eof())
	{
		ch = f.peek();
		
		if (ch!=10)  //return char
		{
			
			f>>lst[r][c];
			c++;
			if (c>colNum)
				colNum = c;
		}
		else
		{
			f.ignore();
			r++;
			setCol(c);
			c =0;
		}
	}
	if (r!=0)
	{
		setRow(r+1);
	}
}


void Matrix::initialize()
{
	for (int r=0; r < rowNum; r++)
	{
		for (int c=0; c< colNum; c++)
		{
			lst[r][c] = r*2+c;
		}
	}	
}


void Matrix::display()
{
//	int temp;
	long preFlag;
	preFlag = cout.flags();
//	temp = cout.precision(4);
//	cout.setf(ios::fixed);
	
	cout<<"\nrow\\col";
	for (int c=0; c< colNum; c++)
	{
		cout<<"  "<<c;
	}
	cout<<"\n\n";
	for (int r = 0; r< rowNum; r++)
	{
		cout<<r<<"\t ";
		for (c = 0; c< colNum; c++)
		{
			cout<<(fabs(lst[r][c])<LIMIT?0:lst[r][c])<<"  ";			
		}
		cout<<endl;
	}
//	cout.precision(temp);
	cout.flags(preFlag);
}

Matrix::Matrix()
{
	rowNum = 5;
	colNum = 5;
	initialize();
}



¡¡

The original matrix is like following:(pls pay attention that the diagonal entry in second row is 0. It prevents you from making all diagonal entries to be 1. But still you have to solve it by going to next row but

keeping the same column. When you finish all rows, if your column has not reached the minimum of  both row and

column, you have to go on. Understand?)

¡¡

1 6 2 4
0 0 1 5
2 0 0 6

¡¡

And the output file is like following:

row\col  0  1  2  3

0        1  6  2  4
1        0  0  1  5
2        2  0  0  6

row\col  0  1  2  3

0        1  0  0  3
1        0  0  1  5
2        0  1  0  -1.5
Press any key to continue

¡¡

As for LHRRCC, you have to input two double array. The first one is the n distinct roots and the second is the

n initial value of Recursive Relation. Got it?

¡¡


¡¡

                                                        back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)

Hosted by www.Geocities.ws

1