mirror of
https://github.com/guilhermewerner/paa
synced 2025-06-16 13:34:18 +00:00
Incidence matrix
This commit is contained in:
267
Source/Graph.cpp
267
Source/Graph.cpp
@ -1,194 +1,125 @@
|
|||||||
#include "Graph.h"
|
#include "Graph.h"
|
||||||
|
|
||||||
void Graph::Insert(int u, int v)
|
void Graph::PrintIncidenceMatrix()
|
||||||
{
|
{
|
||||||
InsertD(u, v);
|
|
||||||
InsertD(v, u);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (auto j = adj[i].begin(); j != adj[i].end(); j++)
|
|
||||||
{
|
|
||||||
graph->InsertD(i, *j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return graph;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graph::DFS(int u, vector<int> &disc, vector<int> &low, vector<int> &parent, vector<pair<int, int>> &bridge)
|
|
||||||
{
|
|
||||||
static int time = 0;
|
|
||||||
disc[u] = low[u] = time;
|
|
||||||
time += 1;
|
|
||||||
|
|
||||||
for (auto v : adj[u])
|
|
||||||
{
|
|
||||||
// vertice não visitado
|
|
||||||
if (disc[v] == -1)
|
|
||||||
{
|
|
||||||
parent[v] = u;
|
|
||||||
DFS(v, disc, low, parent, bridge);
|
|
||||||
low[u] = min(low[u], low[v]);
|
|
||||||
|
|
||||||
if (low[v] > disc[u])
|
|
||||||
{
|
|
||||||
bridge.push_back({u, v});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graph::TransitiveClosure2()
|
|
||||||
{
|
|
||||||
// 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 << " ";
|
cout << " ";
|
||||||
|
|
||||||
for (int j = 0; j < length; j++)
|
for (int j = 0; j < edges; j++)
|
||||||
{
|
{
|
||||||
cout << j << " ";
|
cout << j << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "\n";
|
cout << endl;
|
||||||
|
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < nodes; i++)
|
||||||
{
|
{
|
||||||
cout << i << " ";
|
cout << i << " ";
|
||||||
|
|
||||||
for (int j = 0; j < length; j++)
|
for (int j = 0; j < edges; j++)
|
||||||
{
|
{
|
||||||
if (i == j)
|
int val = this->matrix[i][j];
|
||||||
|
|
||||||
|
if (val >= 0)
|
||||||
{
|
{
|
||||||
cout << "1 ";
|
cout << " " << val << " ";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cout << reach[i][j] << " ";
|
cout << val << " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << "\n";
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Graph::AddEdge(int u, int v)
|
||||||
|
{
|
||||||
|
this->matrix[u][this->edges] = 1;
|
||||||
|
this->matrix[v][this->edges] = -1;
|
||||||
|
this->edges++;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<vector<int>> Graph::GetAdjacencyMatrix()
|
||||||
|
{
|
||||||
|
vector<vector<int>> adjacency(this->nodes, vector<int>(this->nodes, 0));
|
||||||
|
|
||||||
|
// Converte uma matriz de incidência para de adjacência.
|
||||||
|
for (int j = 0; j < this->edges; j++)
|
||||||
|
{
|
||||||
|
int u = -1, v = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < this->nodes; i++)
|
||||||
|
{
|
||||||
|
if (this->matrix[i][j] == 1)
|
||||||
|
{
|
||||||
|
if (u == -1)
|
||||||
|
{
|
||||||
|
u = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (this->matrix[i][j] == -1)
|
||||||
|
{
|
||||||
|
if (v == -1)
|
||||||
|
{
|
||||||
|
v = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graph::TransitiveReduce()
|
if (u != -1 && v != -1)
|
||||||
{
|
{
|
||||||
for (auto a = 0; a < length; a++)
|
adjacency[u][v] = 1;
|
||||||
{
|
|
||||||
for (auto b = 0; b < length; b++)
|
|
||||||
{
|
|
||||||
if (HasEdge(a, b))
|
|
||||||
{
|
|
||||||
for (auto c = 0; c < length; c++)
|
|
||||||
{
|
|
||||||
if (HasEdge(b, c))
|
|
||||||
{
|
|
||||||
// this->RemoveD();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return adjacency;
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<vector<int>> Graph::GetIncidenceMatrix()
|
||||||
|
{
|
||||||
|
vector<vector<int>> 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()
|
void Graph::TransitiveClosure()
|
||||||
{
|
{
|
||||||
int m1[length][length];
|
int m1[length][length];
|
||||||
@ -235,11 +166,18 @@ void Graph::TransitiveClosure()
|
|||||||
for (auto i = 0; i < length; i++)
|
for (auto i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
for (auto j = 0; j < length; j++)
|
for (auto j = 0; j < length; j++)
|
||||||
|
{
|
||||||
|
if (i == j)
|
||||||
|
{
|
||||||
|
m2[i][j] = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
m2[i][j] = m2[i][j] || (m2[i][k] && m2[k][j]);
|
m2[i][j] = m2[i][j] || (m2[i][k] && m2[k][j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cout << "\nM2:" << endl;
|
cout << "\nM2:" << endl;
|
||||||
|
|
||||||
@ -286,8 +224,14 @@ void Graph::TransitiveClosure()
|
|||||||
{
|
{
|
||||||
for (auto j = 0; j < length; j++)
|
for (auto j = 0; j < length; j++)
|
||||||
{
|
{
|
||||||
int temp = m1[i][j] - m3[i][j];
|
if (m1[i][j] >= 1 && m3[i][j] >= 1)
|
||||||
m3[i][j] = temp > 0 ? temp : 0;
|
{
|
||||||
|
m3[i][j] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m3[i][j] = m1[i][j];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,3 +247,4 @@ void Graph::TransitiveClosure()
|
|||||||
cout << endl;
|
cout << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
122
Source/Graph.h
122
Source/Graph.h
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <bits/stdc++.h>
|
#include <bits/stdc++.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
@ -12,34 +13,121 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
const int MATRIX_LENGTH = 100;
|
||||||
|
|
||||||
class Graph
|
class Graph
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int length;
|
int nodes, edges;
|
||||||
list<int> *adj;
|
array<array<int, MATRIX_LENGTH>, MATRIX_LENGTH> matrix;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Graph(int length)
|
Graph(int nodes)
|
||||||
{
|
{
|
||||||
this->length = length;
|
this->nodes = nodes;
|
||||||
this->adj = new list<int>[length];
|
this->edges = 0;
|
||||||
|
this->matrix.fill(array<int, MATRIX_LENGTH>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
~Graph()
|
Graph(const Graph &other)
|
||||||
{
|
{
|
||||||
delete[] adj;
|
this->nodes = other.nodes;
|
||||||
|
this->edges = other.edges;
|
||||||
|
this->matrix = other.matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
Graph(const vector<vector<int>> &incidence)
|
||||||
|
{
|
||||||
|
this->nodes = incidence.size();
|
||||||
|
this->edges = incidence[0].size();
|
||||||
|
this->matrix.fill(array<int, MATRIX_LENGTH>{});
|
||||||
|
|
||||||
|
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<vector<int>> &adjacency, int nodes)
|
||||||
|
{
|
||||||
|
this->nodes = nodes;
|
||||||
|
this->edges = 0;
|
||||||
|
this->matrix.fill(array<int, MATRIX_LENGTH>{});
|
||||||
|
|
||||||
|
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:
|
public:
|
||||||
void Print();
|
void PrintIncidenceMatrix();
|
||||||
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();
|
|
||||||
|
|
||||||
private:
|
void AddEdge(int u, int v);
|
||||||
void DFS(int u, vector<int> &disc, vector<int> &low, vector<int> &parent, vector<pair<int, int>> &bridge);
|
|
||||||
int DFSCount(int v, bool visited[]);
|
vector<vector<int>> GetAdjacencyMatrix();
|
||||||
|
|
||||||
|
vector<vector<int>> GetIncidenceMatrix();
|
||||||
|
|
||||||
|
Graph *ToTransitiveClosure();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void PrintAdjacencyMatrix(const vector<vector<int>> &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<vector<int>> MultiplyIncidenceMatrix(const vector<vector<int>> &left, const vector<vector<int>> &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<vector<int>> result(rows1 * rows2, vector<int>(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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,17 +2,28 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int length = 4;
|
int nodes = 4;
|
||||||
Graph *g1 = new Graph(length);
|
Graph *g1 = new Graph(nodes);
|
||||||
|
|
||||||
g1->InsertD(0, 1);
|
g1->AddEdge(0, 1); // Edge 0
|
||||||
g1->InsertD(0, 2);
|
g1->AddEdge(0, 2); // Edge 1
|
||||||
g1->InsertD(1, 2);
|
g1->AddEdge(1, 2); // Edge 2
|
||||||
g1->InsertD(2, 0);
|
g1->AddEdge(2, 0); // Edge 3
|
||||||
g1->InsertD(2, 3);
|
g1->AddEdge(2, 3); // Edge 4
|
||||||
|
|
||||||
cout << "-- TRANSITIVE CLOSURE --\n\n";
|
cout << "M1:" << endl;
|
||||||
g1->TransitiveClosure();
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user