From 84b9021b22dcfa415957d78fb4431e436615ca7d Mon Sep 17 00:00:00 2001 From: Guilherme Werner Date: Sun, 18 Jun 2023 12:00:15 -0300 Subject: [PATCH] Incidence matrix --- Source/Graph.cpp | 269 +++++++++++++++++++---------------------------- Source/Graph.h | 122 ++++++++++++++++++--- Source/Main.cpp | 29 +++-- 3 files changed, 232 insertions(+), 188 deletions(-) diff --git a/Source/Graph.cpp b/Source/Graph.cpp index 2b779c7..ab639f3 100644 --- a/Source/Graph.cpp +++ b/Source/Graph.cpp @@ -1,194 +1,125 @@ #include "Graph.h" -void Graph::Insert(int u, int v) +void Graph::PrintIncidenceMatrix() { - InsertD(u, v); - InsertD(v, u); -} + cout << " "; -void Graph::InsertD(int u, int v) -{ - adj[u].push_back(v); -} - -void Graph::Remove(int u, int v) -{ - RemoveD(u, v); - RemoveD(v, u); -} - -void Graph::RemoveD(int u, int v) -{ - auto iv = find(adj[u].begin(), adj[u].end(), v); - *iv = -1; -} - -bool Graph::HasEdge(int u, int v) -{ - auto iv = find(adj[u].begin(), adj[u].end(), v); - return (iv != adj[u].end()); -} - -Graph *Graph::Clone() -{ - Graph *graph = new Graph(length); - - for (auto i = 0; i < length; i++) + for (int j = 0; j < edges; j++) { - for (auto j = adj[i].begin(); j != adj[i].end(); j++) - { - graph->InsertD(i, *j); - } + cout << j << " "; } - return graph; -} + cout << endl; -void Graph::DFS(int u, vector &disc, vector &low, vector &parent, vector> &bridge) -{ - static int time = 0; - disc[u] = low[u] = time; - time += 1; - - for (auto v : adj[u]) + for (int i = 0; i < nodes; i++) { - // vertice não visitado - if (disc[v] == -1) - { - parent[v] = u; - DFS(v, disc, low, parent, bridge); - low[u] = min(low[u], low[v]); + cout << i << " "; - if (low[v] > disc[u]) + for (int j = 0; j < edges; j++) + { + int val = this->matrix[i][j]; + + if (val >= 0) { - bridge.push_back({u, v}); + cout << " " << val << " "; + } + else + { + cout << val << " "; } - } - else if (v != parent[u]) - { - low[u] = min(low[u], disc[v]); - } - } -} - -int Graph::DFSCount(int v, bool visited[]) -{ - // marcar vertice como visitado - visited[v] = true; - int count = 1; - - for (auto i = adj[v].begin(); i != adj[v].end(); ++i) - { - if (*i != -1 && !visited[*i]) - { - count += DFSCount(*i, visited); - } - } - - return count; -} - -void Graph::Print() -{ - for (auto i = 0; i < length; i++) - { - cout << "[" << i << "]: "; - - for (auto j = adj[i].begin(); j != adj[i].end(); j++) - { - cout << *j << " "; } cout << endl; } + + cout << endl; } -void Graph::TransitiveClosure2() +void Graph::AddEdge(int u, int v) { - // Populate matrix - - int reach[length][length]; - - for (auto i = 0; i < length; i++) - { - for (auto j = 0; j < length; j++) - { - reach[i][j] = 0; - } - } - - for (auto i = 0; i < length; i++) - { - for (auto j = adj[i].begin(); j != adj[i].end(); j++) - { - reach[i][*j] = 1; - } - } - - // Transitive closure - - for (auto k = 0; k < length; k++) - { - for (auto i = 0; i < length; i++) - { - for (auto j = 0; j < length; j++) - { - reach[i][j] = reach[i][j] || (reach[i][k] && reach[k][j]); - } - } - } - - // Print matrix - - cout << " "; - - for (int j = 0; j < length; j++) - { - cout << j << " "; - } - - cout << "\n"; - - for (int i = 0; i < length; i++) - { - cout << i << " "; - - for (int j = 0; j < length; j++) - { - if (i == j) - { - cout << "1 "; - } - else - { - cout << reach[i][j] << " "; - } - } - - cout << "\n"; - } + this->matrix[u][this->edges] = 1; + this->matrix[v][this->edges] = -1; + this->edges++; } -void Graph::TransitiveReduce() +vector> Graph::GetAdjacencyMatrix() { - for (auto a = 0; a < length; a++) + vector> adjacency(this->nodes, vector(this->nodes, 0)); + + // Converte uma matriz de incidência para de adjacência. + for (int j = 0; j < this->edges; j++) { - for (auto b = 0; b < length; b++) + int u = -1, v = -1; + + for (int i = 0; i < this->nodes; i++) { - if (HasEdge(a, b)) + if (this->matrix[i][j] == 1) { - for (auto c = 0; c < length; c++) + if (u == -1) { - if (HasEdge(b, c)) - { - // this->RemoveD(); - } + u = i; + } + } + else if (this->matrix[i][j] == -1) + { + if (v == -1) + { + v = i; + } + } + } + + if (u != -1 && v != -1) + { + adjacency[u][v] = 1; + } + } + + return adjacency; +} + +vector> Graph::GetIncidenceMatrix() +{ + vector> incidence(this->nodes); + + for (int i = 0; i < this->nodes; i++) + { + for (int j = 0; j < this->edges; j++) + { + incidence[i].push_back(this->matrix[i][j]); + } + } + + return incidence; +} + +Graph *Graph::ToTransitiveClosure() +{ + auto closure = this->GetAdjacencyMatrix(); + + // Calcula o fecho transitivo do grafo. + for (auto k = 0; k < this->nodes; k++) + { + for (auto i = 0; i < this->nodes; i++) + { + for (auto j = 0; j < this->nodes; j++) + { + if (i == j) + { + closure[i][j] = 1; + } + else + { + closure[i][j] = closure[i][j] || (closure[i][k] && closure[k][j]); } } } } + + return new Graph(closure, closure.size()); } +/* void Graph::TransitiveClosure() { int m1[length][length]; @@ -236,7 +167,14 @@ void Graph::TransitiveClosure() { for (auto j = 0; j < length; j++) { - m2[i][j] = m2[i][j] || (m2[i][k] && m2[k][j]); + if (i == j) + { + m2[i][j] = 1; + } + else + { + m2[i][j] = m2[i][j] || (m2[i][k] && m2[k][j]); + } } } } @@ -286,8 +224,14 @@ void Graph::TransitiveClosure() { for (auto j = 0; j < length; j++) { - int temp = m1[i][j] - m3[i][j]; - m3[i][j] = temp > 0 ? temp : 0; + if (m1[i][j] >= 1 && m3[i][j] >= 1) + { + m3[i][j] = 0; + } + else + { + m3[i][j] = m1[i][j]; + } } } @@ -303,3 +247,4 @@ void Graph::TransitiveClosure() cout << endl; } } +*/ diff --git a/Source/Graph.h b/Source/Graph.h index ac495ad..158f6eb 100644 --- a/Source/Graph.h +++ b/Source/Graph.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -12,34 +13,121 @@ using namespace std; +const int MATRIX_LENGTH = 100; + class Graph { private: - int length; - list *adj; + int nodes, edges; + array, MATRIX_LENGTH> matrix; public: - Graph(int length) + Graph(int nodes) { - this->length = length; - this->adj = new list[length]; + this->nodes = nodes; + this->edges = 0; + this->matrix.fill(array{}); } - ~Graph() + Graph(const Graph &other) { - delete[] adj; + this->nodes = other.nodes; + this->edges = other.edges; + this->matrix = other.matrix; + } + + Graph(const vector> &incidence) + { + this->nodes = incidence.size(); + this->edges = incidence[0].size(); + this->matrix.fill(array{}); + + for (int i = 0; i < this->nodes; i++) + { + for (int j = 0; j < this->edges; j++) + { + this->matrix[i][j] = incidence[i][j]; + } + } + } + + Graph(const vector> &adjacency, int nodes) + { + this->nodes = nodes; + this->edges = 0; + this->matrix.fill(array{}); + + for (int i = 0; i < this->nodes; i++) + { + for (int j = 0; j < this->nodes; j++) + { + if (adjacency[i][j] == 1) + { + this->AddEdge(i, j); + } + } + } + } + + Graph *Clone() const + { + return new Graph(*this); } public: - void Print(); - void Insert(int u, int v); - void InsertD(int u, int v); - void Remove(int u, int v); - void RemoveD(int u, int v); - void TransitiveClosure(); - Graph *Clone(); + void PrintIncidenceMatrix(); -private: - void DFS(int u, vector &disc, vector &low, vector &parent, vector> &bridge); - int DFSCount(int v, bool visited[]); + void AddEdge(int u, int v); + + vector> GetAdjacencyMatrix(); + + vector> GetIncidenceMatrix(); + + Graph *ToTransitiveClosure(); + +public: + static void PrintAdjacencyMatrix(const vector> &adjacency) + { + int nodes = adjacency.size(); + + for (int i = 0; i < nodes; i++) + { + for (int j = 0; j < nodes; j++) + { + cout << adjacency[i][j] << " "; + } + + cout << endl; + } + + cout << endl; + } + + static vector> MultiplyIncidenceMatrix(const vector> &left, const vector> &right) + { + int rows1 = left.size(); + int cols1 = left[0].size(); + int rows2 = right.size(); + int cols2 = right[0].size(); + + // Cria a matriz de resultado com o número de linhas de matrix1 e o número de colunas de matrix2 + vector> result(rows1 * rows2, vector(cols1 * cols2, 0)); + + // Realiza a multiplicação tensorial das matrizes de incidência + for (int i = 0; i < rows1; i++) + { + for (int j = 0; j < cols1; j++) + { + for (int k = 0; k < rows2; k++) + { + for (int l = 0; l < cols2; l++) + { + result[i * rows2 + k][j * cols2 + l] = left[i][j] * right[k][l]; + } + } + } + } + + return result; + } }; diff --git a/Source/Main.cpp b/Source/Main.cpp index 9eb2e5a..5f243c4 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -2,17 +2,28 @@ int main() { - int length = 4; - Graph *g1 = new Graph(length); + int nodes = 4; + Graph *g1 = new Graph(nodes); - g1->InsertD(0, 1); - g1->InsertD(0, 2); - g1->InsertD(1, 2); - g1->InsertD(2, 0); - g1->InsertD(2, 3); + g1->AddEdge(0, 1); // Edge 0 + g1->AddEdge(0, 2); // Edge 1 + g1->AddEdge(1, 2); // Edge 2 + g1->AddEdge(2, 0); // Edge 3 + g1->AddEdge(2, 3); // Edge 4 - cout << "-- TRANSITIVE CLOSURE --\n\n"; - g1->TransitiveClosure(); + cout << "M1:" << endl; + g1->PrintIncidenceMatrix(); + auto m1 = g1->GetIncidenceMatrix(); + + Graph *g2 = g1->ToTransitiveClosure(); + cout << "M2:" << endl; + g2->PrintIncidenceMatrix(); + auto m2 = g2->GetIncidenceMatrix(); + + auto m3 = Graph::MultiplyIncidenceMatrix(m1, m2); + Graph *g3 = new Graph(m3); + cout << "M3:" << endl; + g3->PrintIncidenceMatrix(); return 0; }