#pragma once
#include <iostream>
#include <vector>
#include <stdarg.h>
#include <set>
#include <map>
#include <initializer_list>
#define endll "\n"
using namespace std;
class _Matrix
{
protected:
int rows;
int cols;
vector<vector<int>> v;
public:
_Matrix() : rows(0), cols(0) {}
_Matrix(int rows, int cols) : rows(rows), cols(cols)
{
for (int i = 0; i < rows; ++i)
{
v.push_back(vector<int>(cols));
}
}
virtual bool scanf_initalize()
{
int temp;
for (int i = 0; i < rows; ++i)
{
vector<int> vv;
for (int j = 0; j < cols; ++j)
{
scanf("%d", &temp);
vv.push_back(temp);
}
v.at(i) = vv;
}
return true;
}
virtual bool add(int num, ...)
{
if (cols == 0)
{
cols = num;
}
else if (num != cols)
{
throw "The matrix needs to be a rectangle";
}
vector<int> vv(num);
va_list ptr;
int temp;
va_start(ptr, num);
for (int i = 0; i < num; ++i)
{
temp = va_arg(ptr, int);
vv.at(i) = temp;
}
va_end(ptr);
v.push_back(vv);
++rows;
return true;
}
virtual bool set_matrix_element(int row, int cols, int val)
{
if (row <= rows && row >= 0 && cols <= this->rows && cols >= 0)
{
v.at(row - 1).at(cols - 1) = val;
return true;
}
return false;
}
int get_rows() const
{
return rows;
}
int get_cols() const
{
return cols;
}
void display() const //??
{
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
cout << v[i][j] << " ";
}
cout << endll;
}
}
void remove_clear()
{
v.clear();
this->cols = 0;
this->rows = 0;
}
int sum()
{
int s = 0;
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
s += v.at(i).at(j);
}
}
return s;
}
_Matrix inverse()
{
_Matrix m(cols, rows);
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
m.v.at(j).at(i) = v.at(i).at(j);
}
}
return m;
}
_Matrix& operator+=(const _Matrix& m)
{
if (m.cols == this->cols && m.rows == this->rows)
{
for (int i = 0; i < this->rows; ++i)
{
for (int j = 0; j < this->cols; ++j)
{
this->v.at(i).at(j) += m.v.at(i).at(j);
}
}
}
else
{
throw "Different matrices for rows or columns are used";
}
return *this;
}
_Matrix& operator-=(const _Matrix& m)
{
if (m.cols == this->cols && m.rows == this->rows)
{
for (int i = 0; i < this->rows; ++i)
{
for (int j = 0; j < this->cols; ++j)
{
this->v.at(i).at(j) -= m.v.at(i).at(j);
}
}
}
else
{
throw "Different matrices for rows or columns are used";
}
return *this;
}
_Matrix& operator*=(const _Matrix& m)
{
if (this->cols == m.rows)
{
_Matrix temp_m(*this);
this->cols = m.cols;
int element = 0;
v.clear();
for (int i = 0; i < temp_m.rows; ++i)
{
vector<int> temp_element;
for (int k = 0; k < m.cols; ++k)
{
for (int j = 0; j < m.rows; ++j)
{
element += temp_m.v.at(i).at(j) * m.v.at(j).at(k);
}
temp_element.push_back(element);
element = 0;
}
v.push_back(temp_element);
}
return *this;
}
else
{
throw "The number of rows and columns should be equal";
}
}
_Matrix& operator*=(int m)
{
for (int i = 0; i < this->rows; ++i)
{
for (int j = 0; j < this->cols; ++j)
{
this->v.at(i).at(j) *= m;
}
}
return *this;
}
friend _Matrix operator+(_Matrix a, _Matrix b)
{
return a += b;
}
friend _Matrix operator-(_Matrix a, _Matrix b)
{
return a -= b;
}
friend _Matrix operator*(_Matrix a, int b)
{
return (a *= b);
}
friend _Matrix operator*(int b, _Matrix a)
{
return a *= b;
}
friend _Matrix operator*(_Matrix a, _Matrix b)
{
return a *= b;
}
friend ostream& operator<<(ostream& os, const _Matrix& m)
{
m.display();
return os;
}
};
template <typename T>
class RelationSet : public set<pair<T, T>>
{
public:
friend class Relation_matrix;
RelationSet() {}
RelationSet(set<pair<T, T>>& r) : set<pair<T, T>>(r) {}
RelationSet(initializer_list<initializer_list<T>> il)
{
for (auto it = il.begin(); it != il.end(); ++it)
{
if (it->size() > 2)
throw "Ordered couple needs two elements";
auto itt = it->begin();
int first_ = *itt;
int second_ = *(++itt);
this->emplace(first_, second_);
}
}
void display() const
{
cout << "{";
auto in_end = this->end();
in_end--;
for (auto it = this->begin(); it != in_end; ++it)
{
cout << "<" << it->first << "," << it->second << ">"
<< ",";
}
cout << "<" << in_end->first << "," << in_end->second << ">"
<< "}";
}
friend ostream& operator<<(ostream& os, const RelationSet& m)
{
m.display();
return os;
}
};
class Relation_matrix : public _Matrix
{
protected:
bool isBitMatrix;
bool equal_randc() const
{
return (rows == cols);
}
bool is_bit_matrix() const
{
return isBitMatrix;
}
void throw_exception() const
{
if (!equal_randc())
throw "It's not a determinant";
if (!is_bit_matrix())
throw "It's not a binary matrix";
}
template<typename T>
static void seach(T t, RelationSet<T>& r, set<T>& temp) {
for (auto i = r.begin(); i != r.end(); ++i) {
if (i->first == t && temp.find(i->second) == temp.end()) {
temp.insert(i->second);
seach(i->second, r, temp);
}
}
}
public:
Relation_matrix(int r_and_c) : _Matrix(r_and_c, r_and_c), isBitMatrix(true)
{
}
Relation_matrix() : _Matrix(), isBitMatrix(true) {}
template <typename T>
Relation_matrix(set<T>& s, RelationSet<T>& r) : _Matrix(s.size(), s.size()), isBitMatrix(true)
{
for (auto it = r.begin(); it != r.end(); ++it)
{
if (s.find(it->first) == s.end() || s.find(it->second) == s.end())
throw "The relation is not defined on the set";
}
map<T, int> m;
int i = 0;
for (auto it = s.begin(); it != s.end(); ++it)
{
m.emplace(*it, i);
++i;
}
for (auto it = r.begin(); it != r.end(); ++it)
{
v.at(m.find(it->first)->second).at(m.find(it->second)->second) = 1;
}
}
bool scanf_initalize() override
{
int temp;
for (int i = 0; i < rows; ++i)
{
vector<int> vv;
for (int j = 0; j < cols; ++j)
{
scanf("%d", &temp);
if (temp != 0 || temp != 1)
{
isBitMatrix = false;
}
vv.push_back(temp);
}
v.at(i) = vv;
}
return true;
}
bool add(int num, ...) override
{
if (cols == 0)
{
cols = num;
}
else if (num != cols)
{
throw "The matrix needs to be a rectangle";
}
vector<int> vv(num);
va_list ptr;
int temp;
va_start(ptr, num);
for (int i = 0; i < num; ++i)
{
temp = va_arg(ptr, int);
if (temp != 1 && temp != 0)
isBitMatrix = false;
vv.at(i) = temp;
}
va_end(ptr);
v.push_back(vv);
++rows;
return true;
}
bool set_matrix_element(int row, int cols, int val) override
{
if (row <= rows && row >= 0 && cols <= this->rows && cols >= 0 && (val == 1 || val == 0))
{
v.at(row - 1).at(cols - 1) = val;
return true;
}
return false;
}
Relation_matrix& operator|=(const Relation_matrix& d)
{
this->throw_exception();
d.throw_exception();
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < d.cols; ++j)
{
if (v.at(i).at(j) | d.v.at(i).at(j))
{
v.at(i).at(j) = 1;
}
else
{
v.at(i).at(j) = 0;
}
}
}
return *this;
}
friend Relation_matrix operator|(Relation_matrix a, Relation_matrix b)
{
a |= b;
return a;
}
bool is_reflexive() const
{
throw_exception();
for (int i = 0; i < rows; ++i)
{
if (v.at(i).at(i) == 0)
return false;
}
return true;
}
bool is_anti_reflexive() const
{
throw_exception();
for (int i = 0; i < rows; ++i)
{
if (v.at(i).at(i) == 1)
return false;
}
return true;
}
bool is_symmetric() const
{
throw_exception();
for (int i = 0; i < rows - 1; ++i)
{
for (int j = i + 1; j < cols; ++j)
{
if (v.at(i).at(j) != v.at(j).at(i))
{
return false;
}
}
}
return true;
}
bool is_anti_symmetric() const
{
throw_exception();
for (int i = 0; i < rows - 1; ++i)
{
for (int j = i + 1; j < cols; ++j)
{
if (v.at(i).at(j) == 1 && v.at(j).at(i) == 1)
{
return false;
}
}
}
return true;
}
bool is_transmit() const
{
throw_exception();
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
for (int k = 0; k < cols; ++k)
{
if (v.at(i).at(j) == 1 && v.at(j).at(k) == 1 && v.at(i).at(k) != 1)
{
return false;
}
}
}
}
return true;
}
bool is_equal() const
{
return is_reflexive() && is_symmetric() && is_transmit();
}
template <typename T>
static set<set<T>> make_equal_class(set<T>& s, RelationSet<T>& r)
{
Relation_matrix temp_m(s, r);
set<T> temp_ele; set<set<T>>val_;
set<T>v;
if (temp_m.is_equal())
{
for (auto it = s.begin(); it != s.end(); ++it) {
if (v.find(*it) != v.end())continue;
temp_ele.insert(*it);
seach(*it, r, temp_ele);
val_.insert(temp_ele);
temp_ele.clear();
}
}
return val_;
}
Relation_matrix reflexive_closure() const
{
throw_exception();
if (this->is_reflexive())
{
return *this;
}
Relation_matrix temp(*this);
for (int i = 0; i < rows; ++i)
{
temp.v.at(i).at(i) = 1;
}
return temp;
}
Relation_matrix symmetric_closure() const
{
throw_exception();
if (this->is_symmetric())
{
return *this;
}
Relation_matrix temp(*this);
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
if (i != j && v.at(i).at(j) == 1 && v.at(j).at(i) == 0)
{
temp.v.at(j).at(i) = 1;
}
}
}
return temp;
}
Relation_matrix transmit_closure() const
{
throw_exception();
if (this->is_transmit())
{
return *this;
}
Relation_matrix temp(*this);
Relation_matrix temp3(*this);
for (int i = 0; i < rows - 1; ++i)
{
temp *= *this;
temp3 |= temp;
}
return temp3;
}
Relation_matrix warshall() const
{
throw_exception();
if (this->is_transmit())
{
return *this;
}
Relation_matrix temp(*this);
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
if (temp.v.at(j).at(i) == 1)
{
for (int k = 0; k < rows; ++k)
{
if (temp.v.at(j).at(k) + temp.v.at(i).at(k))
temp.v.at(j).at(k) = 1;
else
temp.v.at(j).at(k) = 0;
}
}
}
}
return temp;
}
template <typename T>
RelationSet<T> make_RelationSet(set<T>& s) const
{
RelationSet<T> r;
map<T, int> m;
int i = 0;
for (auto it = s.begin(); it != s.end(); ++it)
{
m.emplace(i, *it);
++i;
}
for (int i = 0; i < this->rows; ++i)
{
for (int j = 0; j < this->rows; ++j)
{
if (v.at(i).at(j) == 1)
{
r.emplace(m.find(i)->second, m.find(j)->second);
}
}
}
return r;
}
};
分装的不好,应付一下离散数学还是可以的。(有些bug,懒得改了,重在能跑)。