Skip to content

Commit

Permalink
feat/test/ get vertex by key and add isConnected tests
Browse files Browse the repository at this point in the history
  • Loading branch information
brunolnetto committed Feb 13, 2022
1 parent 2b427eb commit 11faa9b
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 34 deletions.
93 changes: 75 additions & 18 deletions data-structures/graph/Graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export default class Graph {
* @param {integer} vertexIndex
* @returns GraphVertex
*/
getVertexByIndex(vertexIndex) {
getVertexByIndex(vertexIndex) {
let adjList=this.getAdjacencyList();
return this.vertices[adjList[vertexIndex]];
}
Expand Down Expand Up @@ -125,6 +125,29 @@ export default class Graph {
return Object.values(this.edges);
}

/**
* @param {integer} vertexIndex
* @returns GraphVertex
*/
getEdgesByVertexKeys(vertexKeys) {
let edges_from_keys=[]
let edges=this.getAllEdges();

for(let i=0; i<edges.length; i = i + 1){
let edge=edges[i]

let startVertexKey = edge.startVertex.getKey();
let endVertexKey = edge.endVertex.getKey();

if(vertexKeys.includes(startVertexKey) &&
vertexKeys.includes(endVertexKey)){
edges_from_keys.push(_.cloneDeep(edge));
}
}

return edges_from_keys;
}

/**
* @returns {Object}
*/
Expand Down Expand Up @@ -326,6 +349,26 @@ export default class Graph {
return this.getAllEdges().reduce((weight, graphEdge) => weight + graphEdge.weight, 0);
}

getForwardDegrees() {
const adjList = this.getAdjacencyList();

return Object
.values(adjList)
.map((to_neighbours) => {
return to_neighbours.length
})
}

getReverseDegrees() {
const adjList = this.getAdjacencyList(1);

return Object
.values(adjList)
.map((to_neighbours) => {
return to_neighbours.length
})
}

/**
* @return {object}
*/
Expand Down Expand Up @@ -577,33 +620,43 @@ export default class Graph {
const n_vertices = this.getNumVertices();
const adjList = this.getAdjacencyList();
const edges = this.getAllEdges();

// If there are no edges in the graph, return true
// If there are no edges in the graph, return false
if (edges.length == 0){
return true;
return false;
}

// Mark all the vertices as not visited
let visited = new Array(n_vertices);
let i;
for (i = 0; i < n_vertices; i++){
for (let i = 0; i < n_vertices; i++){
visited[i] = false;
}

// Find a vertex with non-zero degree
for (i = 0; i < n_vertices; i++) {
if (adjList[i].length != 0) {
break;
}

let forward_degrees = this.getForwardDegrees();
let reverse_degrees = this.getReverseDegrees();

let summedDegrees=[]
for(let i=0; i<n_vertices; i = i + 1) {
summedDegrees[i]=reverse_degrees[i]+forward_degrees[i]
}

// Start DFS traversal from a vertex with non-zero degree
this.DFSUtil(i, visited);
let zero_summed_degrees=summedDegrees.filter((summedDegree) => summedDegree==0)

if(zero_summed_degrees.length!=0)
return false

// Check if all non-zero degree vertices are visited
for (i = 0; i < n_vertices; i++){
if (visited[i] == false && adjList[i].length > 0){
return false;
// Find a vertex with non-zero degree
for (let i=0; i<n_vertices; i = i + 1) {
if(adjList[i].length!=0) {
// Start DFS traversal from a vertex with non-zero degree
this.DFSUtil(i, visited);

// Check if all non-zero degree vertices are visited
for (let j = 0; j < n_vertices; j=j+1){
if (visited[j] == false && adjList[i].length > 0){
return false;
}
}
}
}

Expand Down Expand Up @@ -1117,6 +1170,10 @@ export default class Graph {
}

allPaths(from, to) {
if(!this.isCyclic){
return this.acyclicPaths();
}

let cycles_venn = this.getCyclesVenn();
let cycle_indices = this.getCycleIndices();

Expand Down
114 changes: 98 additions & 16 deletions data-structures/graph/__test__/Graph.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,37 @@ describe('Graph', () => {
expect(graph.getVertexByKey(B.getKey())).toEqual(B);
});

it('should get vertex by its index', () => {
const graph = new Graph();

const [A, B] = createVertices(['A', 'B']);

graph.addVertices([A, B]);

let vertex = graph.getVertexByIndex(0)

expect(vertex.getKey()).toEqual('A');
});

it('should get edges by vertex keys', () => {
const graph = new Graph();
let keys = ['A', 'B', 'C'];

const [A, B, C] = createVertices(keys);
const [AB, BC] = createEdges([[A, B], [B, C]]);

graph.addEdges([AB, BC]);

let edges = graph.getEdgesByVertexKeys(keys)

let edge_keys=[]
edges.forEach((edge) => {
edge_keys.push(edge.getKey())
})

expect(edge_keys).toEqual(['A_B', 'B_C']);
});

it('should add edges to undirected graph', () => {
const graph = new Graph();

Expand Down Expand Up @@ -344,6 +375,26 @@ describe('Graph', () => {
expect(graph.cyclicCircuits()).toStrictEqual([[1, 2, 4], [1, 2, 5]]);
});

it('should return true for strongly connected graph', () => {
let vertex_keys=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']

const [A, B, C, D, E, F, G, H] = createVertices(vertex_keys);

let [AB, AC, CD, BD,
EF, EG, FH, GH,
DE]=createEdges([[A, B], [B, C], [C, D], [D, A],
[E, F], [F, G], [G, H], [H, E],
[D, E]])

const graph = new Graph(true);

graph.addEdges([AB, AC, CD, BD, EF, EG, FH, GH, DE]);

let SCComponents = graph.getStronglyConnectedComponents();

expect(SCComponents).toEqual([[0, 3, 2, 1], [4, 7, 6, 5]]);
});

it('Bridges in graph', () => {
// A directed graph
const graph = new Graph(true);
Expand Down Expand Up @@ -593,22 +644,13 @@ describe('Graph', () => {
const graph_ = new Graph(true);

// Nodes
const A = new GraphVertex('A');
const B = new GraphVertex('B');
const C = new GraphVertex('C');
const D = new GraphVertex('D');
const E = new GraphVertex('E');
const F = new GraphVertex('F');
let [A, B, C, D, E, F] = createVertices(['A', 'B', 'C', 'D', 'E', 'F'])

// Vertices
const AB = new GraphEdge(A, B);
const BC = new GraphEdge(B, C);
const CD = new GraphEdge(C, D);
const CE = new GraphEdge(C, E);
const EB = new GraphEdge(E, B);
const CF = new GraphEdge(C, F);
const FB = new GraphEdge(F, B);

const [AB, BC, CD, CE,
EB, CF, FB] = new createEdges([[A, B], [B, C], [C, D], [C, E],
[E, B], [C, F], [F, B]]);

// Add edges
graph_.addEdges([AB, BC, CD, CE, EB, CF, FB]);

Expand Down Expand Up @@ -726,7 +768,21 @@ describe('Graph', () => {
expect(graph.isConnected()).toEqual(true);
});

it('should return true for graph without edges', () => {
it('should return false for not-connected graph', () => {
const graph = new Graph(true);

// Nodes
let [A, B, C] = createVertices(['A', 'B', 'C']);
let [AB] = createEdges([[A, B]]);

// Add edges
graph.addVertices([A, B, C]);
graph.addEdges([AB]);

expect(graph.isConnected()).toEqual(false);
});

it('should return true for connected graph', () => {
const graph = new Graph(true);

// Nodes
Expand All @@ -737,11 +793,37 @@ describe('Graph', () => {
const E = new GraphVertex('E');
const F = new GraphVertex('F');

graph.addVertices([A, B, C, D, E, F])
// Vertices
const AB = new GraphEdge(A, B);
const BC = new GraphEdge(B, C);
const CD = new GraphEdge(C, D);
const CE = new GraphEdge(C, E);
const EB = new GraphEdge(E, B);
const CF = new GraphEdge(C, F);
const FB = new GraphEdge(F, B);

// Add edges
graph.addEdges([AB, BC, CD, CE, EB, CF, FB]);

expect(graph.isConnected()).toEqual(true);
});

it('should return false for graph without edges', () => {
const graph = new Graph(true);

// Nodes
const A = new GraphVertex('A');
const B = new GraphVertex('B');
const C = new GraphVertex('C');
const D = new GraphVertex('D');
const E = new GraphVertex('E');
const F = new GraphVertex('F');

graph.addVertices([A, B, C, D, E, F])

expect(graph.isConnected()).toEqual(false);
});

it('should return empty for non-eulerian graph', () => {
const graph = new Graph(true);

Expand Down

0 comments on commit 11faa9b

Please sign in to comment.