Skip to content

Commit

Permalink
Iterators for graph edges and vertices. Use arrays for graph getters …
Browse files Browse the repository at this point in the history
…with no complex data structures.
  • Loading branch information
Neloreck committed Nov 2, 2023
1 parent ca2f50f commit 9ce90c5
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 31 deletions.
38 changes: 19 additions & 19 deletions src/graph/DirectedGraph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ describe("DirectedGraph class", () => {
it("should correctly initialize from set", () => {
const graph: DirectedGraph<number> = new DirectedGraph([1, 3, 5]);

expect(graph.getEdges().size).toBe(0);
expect(graph.getVertices().size).toBe(3);
expect(graph.getEdges()).toHaveLength(0);
expect(graph.getVertices()).toHaveLength(3);

expect(graph.getVertices().has(1)).toBe(true);
expect(graph.getVertices().has(3)).toBe(true);
expect(graph.getVertices().has(5)).toBe(true);
expect(graph.getVertices()).toContain(1);
expect(graph.getVertices()).toContain(3);
expect(graph.getVertices()).toContain(5);
});

it("should correctly initialize basic graph", () => {
const graph: DirectedGraph<number> = createBasicTestGraph(5);

expect([...graph.getEdges().values()]).toEqual([]);
expect([...graph.getVertices().values()]).toEqual([0, 1, 2, 3, 4]);
expect(graph.getEdges()).toEqual([]);
expect(graph.getVertices()).toEqual([0, 1, 2, 3, 4]);

expect(graph.getEdge(0, 1)).toBeNull();
expect(graph.hasEdge(0, 1)).toBe(false);
Expand All @@ -44,8 +44,8 @@ describe("DirectedGraph class", () => {
.addEdge(3, 2, threeTwo)
.addEdge(2, 3, twoThree);

expect([...graph.getEdges().values()]).toEqual([oneThree, threeOne, threeTwo, twoThree]);
expect([...graph.getVertices().values()]).toEqual([1, 2, 3]);
expect(graph.getEdges()).toEqual([oneThree, threeOne, threeTwo, twoThree]);
expect(graph.getVertices()).toEqual([1, 2, 3]);

expect(graph.getEdge(1, 2)).toBeNull();
expect(graph.getEdge(2, 1)).toBeNull();
Expand All @@ -58,8 +58,8 @@ describe("DirectedGraph class", () => {
it("should correctly initialize linked graph", () => {
const graph: DirectedGraph<number> = createBasicConnectedTestGraph(3, 2);

expect([...graph.getEdges().values()]).toEqual([{}, {}]);
expect([...graph.getVertices().values()]).toEqual([0, 1, 2]);
expect(graph.getEdges()).toEqual([{}, {}]);
expect(graph.getVertices()).toEqual([0, 1, 2]);

expect(graph.hasEdge(0, 1)).toBe(true);
expect(graph.hasEdge(1, 2)).toBe(true);
Expand All @@ -75,26 +75,26 @@ describe("DirectedGraph class", () => {
expect(graph.getEdge(0, 1)).toBe(edge);
expect(graph.hasEdge(0, 1)).toBe(true);

expect([...graph.getEdges().values()]).toEqual([edge]);
expect([...graph.getVertices().values()]).toEqual([0, 1, 2]);
expect(graph.getEdges()).toEqual([edge]);
expect(graph.getVertices()).toEqual([0, 1, 2]);

graph.removeEdge(1, 2);

expect([...graph.getEdges().values()]).toEqual([edge]);
expect([...graph.getVertices().values()]).toEqual([0, 1, 2]);
expect(graph.getEdges()).toEqual([edge]);
expect(graph.getVertices()).toEqual([0, 1, 2]);

graph.removeEdge(0, 1);

expect([...graph.getEdges().values()]).toEqual([]);
expect([...graph.getVertices().values()]).toEqual([0, 1, 2]);
expect(graph.getEdges()).toEqual([]);
expect(graph.getVertices()).toEqual([0, 1, 2]);
});

it("should correctly add many vertices", () => {
const graph: DirectedGraph<number> = new DirectedGraph();

graph.addVertex(1).addVertex(2).addVertices([3, 4, 5]);

expect(graph.getVertices().size).toBe(5);
expect([...graph.getVertices().values()]).toEqual([1, 2, 3, 4, 5]);
expect(graph.getVertices()).toHaveLength(5);
expect(graph.getVertices()).toEqual([1, 2, 3, 4, 5]);
});
});
23 changes: 18 additions & 5 deletions src/graph/DirectedGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,23 @@ export class DirectedGraph<VertexType, EdgeType extends IEdge = IEdge> implement
/**
* @returns iterator over graph vertices
*/
public [Symbol.iterator](): IterableIterator<VertexType> {
public vertices(): IterableIterator<VertexType> {
return this.data.keys();
}

/**
* @returns iterator over graph vertices
*/
public edges(): IterableIterator<EdgeType> {
const edges: Set<EdgeType> = new Set();

for (const links of this.data.values()) {
links.forEach((edge) => edges.add(edge));
}

return edges.values();
}

/**
* @param vertex - new vertex to add in graph
* @returns this
Expand Down Expand Up @@ -81,21 +94,21 @@ export class DirectedGraph<VertexType, EdgeType extends IEdge = IEdge> implement
/**
* @returns set of vertices
*/
public getVertices(): Set<VertexType> {
return new Set(this.data.keys());
public getVertices(): Array<VertexType> {
return [...this.data.keys()];
}

/**
* @returns set of edges in current graph
*/
public getEdges(): Set<EdgeType> {
public getEdges(): Array<EdgeType> {
const edges: Set<EdgeType> = new Set();

for (const links of this.data.values()) {
links.forEach((edge) => edges.add(edge));
}

return edges;
return [...edges.values()];
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/graph/DirectedWeightedGraph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe("DirectedGraph class", () => {
.addEdge(3, 2, threeTwo)
.addEdge(2, 3, twoThree);

expect(graph.getEdges().size).toBe(4);
expect(graph.getEdges()).toHaveLength(4);
expect(graph.hasEdge(1, 3)).toBe(true);
expect(graph.hasEdge(3, 1)).toBe(true);
expect(graph.hasEdge(2, 3)).toBe(true);
Expand Down
10 changes: 7 additions & 3 deletions src/graph/IGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@ export interface IGraph<VertexType, EdgeType extends IEdge = IEdge> {
/**
* @returns vertices iterator
*/
[Symbol.iterator]: () => IterableIterator<VertexType>;
vertices(): IterableIterator<VertexType>;
/**
* @returns edges iterator
*/
edges(): IterableIterator<EdgeType>;
/**
* @returns all vertices inside the graph
*/
getVertices(): Set<VertexType>;
getVertices(): Array<VertexType>;
/**
* @returns all edges inside the graph
*/
getEdges(): Set<EdgeType>;
getEdges(): Array<EdgeType>;
/**
* @param firstVertex = the vertex from which the edge is coming from
* @param secondVertex - the vertex the edge is going to
Expand Down
4 changes: 2 additions & 2 deletions src/planner/AbstractPlanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export abstract class AbstractPlanner {
const nodesToWorkOn: Array<GraphNode> = [];

// graphNode.action != null -> start and ends
for (const node of graph) {
for (const node of graph.vertices()) {
if (
this.startNode !== node &&
node.action !== null &&
Expand Down Expand Up @@ -244,7 +244,7 @@ export abstract class AbstractPlanner {
): boolean {
let connected: boolean = false;

for (const otherNodeInGraph of graph) {
for (const otherNodeInGraph of graph.vertices()) {
// End nodes can not have an edge towards another node and the target node must not be itself.
// Also, there must not already be an edge in the graph.
// && !graph.hasEdge(node, nodeInGraph) has to be added or loops occur which lead to a crash.
Expand Down
2 changes: 1 addition & 1 deletion src/utils/planner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ describe("planner utils module", () => {
expect(thirdPath?.start).toBe(first);
expect(thirdPath?.end).toBe(fourth);
expect(thirdPath?.vertices).toEqual([first, second, third, fourth]);
expect(thirdPath?.edges).toEqual([...graph.getEdges()]);
expect(thirdPath?.edges).toEqual(graph.getEdges());

expect(addNodeToGraphPathEnd(graph, path as IWeightedPath<GraphNode>, fourth)).toBeNull();
expect(addNodeToGraphPathEnd(graph, path as IWeightedPath<GraphNode>, new GraphNode([], []))).toBeNull();
Expand Down

0 comments on commit 9ce90c5

Please sign in to comment.