Logic Matrix

A.Third Edition
This is the third edition of my my Matrix class and I made some adjustment like to make a public ancestor for
both MathMatrix and LogicMatrix.
B.Idea of program
1¡£ Basic idea: 
To make a logic matrix which is made up of 0's and 1's. In particular, I concentrate on the square matrix. 
Implement some operation like "AND"(similar to multiply in math matrix), "OR"(similar  as plus in math matrix),
"POWER"(n times "and" with original matrix). And some property function like "reflexive, symmetric, antisymmetric,
transitive".
2¡£ Program design: 
Almost same as math matrix except use boolean operation. ¡¡
3¡£ Major function
 A.  Matrix& operator &&(Matrix otherMatrix);
      Matrix& operator ||(Matrix otherMatrix); 
      Matrix& power(int exponent);
Similar to multiply,plus, power of math matrix. but overloading with different operators.

B.

bool reflexive();
bool symmetric();
bool antiSymmetric();
bool transitive();
Matrix& closure();

In closure() function, I actually change matrix itself which is no good. But I am not patient to correct it.

4¡£ Further improvement£º
	A. Make Matrix the common ancestor of MathMatrix and LogicMatrix so that they can share some common 
operations. 
C. I am adding small improvement into third edition and it can be regarded as 3.5 edition.:)
I only add 2 small methods, one is reflexive closure, the other is symmetric closure. They are so simple and 
I am shamed to mention them.	
#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, bool reduced=true);
	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();
};


int main()
{
	LogicMatrix M, N;
	M.readFromFile("c:\\nick.txt");
	N =M;
	/*
	N = M;
	for (int i =1; i<M.col()+1; i++)
	{
		cout<<"power of "<<i<<"\n"<<endl;		
		M.power(i);
		cout<<"reflexive is :"<<M.reflexive()<<endl; 
		cout<<"symmetric is :"<<M.symmetric()<<endl;
		cout<<"antisymmetric is:"<<M.antiSymmetric()<<endl;
		cout<<"transitive is:"<<M.transitive()<<endl;
		M.display();
		cout<<"\n";	
		M = N;
	}
	M = N;
	cout<<"closure\n";
	M.closure();
	*/
	cout<<"reflexive is :"<<M.reflexive()<<endl; 
	cout<<"symmetric is :"<<M.symmetric()<<endl;
	cout<<"antisymmetric is:"<<M.antiSymmetric()<<endl;
	cout<<"transitive is:"<<M.transitive()<<endl;
	M.display();
	cout<<"transitive closure is\n";
	M.transitiveClosure().display();
	M = N;
	cout<<"symmetric Closure is\n";
	M.symmetricClosure().display();
	M =N;
	cout<<"reflextive closure is\n";
	M.reflexiveClosure().display();

	return 0;
}

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);
}


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, bool reduced)
{
	int c=r;
	if (r<row())
	{
		while (c< col())
		{
			if (items(r, c) ==0)
			{
				c++;
			}
			else
			{
				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, reduced);
				break;
			}
		}
	}
	
}

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<<"row\\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:

1 1 0 0 1
0 1 1 1 0
0 0 1 0 1
0 1 0 0 0
0 0 0 0 0

¡¡

And the output file is like following:

reflexive is :0
symmetric is :0
antisymmetric is:0
transitive is:0
row\col  0  1  2  3  4

0	 1  1  0  0  1  
1	 0  1  1  1  0  
2	 0  0  1  0  1  
3	 0  1  0  0  0  
4	 0  0  0  0  0  
transitive closure is
row\col  0  1  2  3  4

0	 1  1  1  1  1  
1	 0  1  1  1  1  
2	 0  0  1  0  1  
3	 0  1  1  1  1  
4	 0  0  0  0  0  
symmetric Closure is
row\col  0  1  2  3  4

0	 1  1  0  0  1  
1	 1  1  1  1  0  
2	 0  1  1  0  1  
3	 0  1  0  0  0  
4	 1  0  1  0  0  
reflextive closure is
row\col  0  1  2  3  4

0	 1  1  0  0  1  
1	 0  1  1  1  0  
2	 0  0  1  0  1  
3	 0  1  0  1  0  
4	 0  0  0  0  1  


¡¡

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

Hosted by www.Geocities.ws

1