Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor graph package (addresses #166) #170

Merged
merged 29 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
72f3a33
Rename some methods in graph.ts
axmmisaka Jun 22, 2023
c308ac0
Remove utility functions of addedge
axmmisaka Jun 22, 2023
8af3083
Update tests accoringly
axmmisaka Jun 22, 2023
33d99f4
Refactor hasCycle() and getOriginsOfEffect()
axmmisaka Jun 22, 2023
c061b06
Add a mermaid.js representation builder
axmmisaka Jun 22, 2023
870ff7b
Add vertices not connected to any edges
axmmisaka Jun 22, 2023
1bc3558
Remove indentation, and fix tests?
axmmisaka Jun 23, 2023
6738255
Directly check cycle without caring about collapsation
axmmisaka Jun 24, 2023
c2347bc
Revert "Directly check cycle without caring about collapsation"
axmmisaka Jun 24, 2023
fa8bfb9
Refactor weeding out port into graph.ts
axmmisaka Jun 24, 2023
98686e5
minor naming changes
axmmisaka Jun 24, 2023
a7171f1
Run prettier
axmmisaka Jun 24, 2023
aab2888
Rename graph APIs
axmmisaka Jun 26, 2023
b6a49de
Changes made together with @axmmmisaka
lhstrh Jun 27, 2023
2c4ba7c
Reverted some changed. Getting all the tests to pass.
lhstrh Jun 27, 2023
9e22241
Commit changes that were not saved
lhstrh Jun 28, 2023
4c080da
Starting to write comments. Some minor API changes.
lhstrh Jun 28, 2023
7b3e092
More comments and API change once again
lhstrh Jun 28, 2023
6f86f3f
Fix tests
axmmisaka Jun 28, 2023
2fea5e7
Fix tests
axmmisaka Jun 28, 2023
36353ee
Revert function signatures to be (origin, effect)
axmmisaka Jun 28, 2023
d0a83b6
Refactor SortablePrecedenceGraph
lhstrh Jun 28, 2023
0199dfe
Roll back some changes
lhstrh Jun 28, 2023
590f4c5
Remove one more unnecessary arg
lhstrh Jun 28, 2023
abea058
Fix comments
lhstrh Jun 28, 2023
6a32662
Add more tests, and fix mermaid edgesWithIssue bug
axmmisaka Jun 28, 2023
c523762
Run prettier on changed files
axmmisaka Jun 28, 2023
e9273c1
Add ReactionGraph class for convenience and readability
lhstrh Jun 28, 2023
554339c
Comments and formatting
lhstrh Jun 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 51 additions & 21 deletions __tests__/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe("Manually constructed simple precedence graphs", () => {
graph.addNode(nodes[0]);

it("graph equality", () => {
expect([...graph.nodes()]).toEqual(nodes);
expect([...graph.getNodes()]).toEqual(nodes);
});
});

Expand Down Expand Up @@ -96,11 +96,21 @@ describe("Manually constructed precedence graphs", () => {
expect(graph.size()[0]).toEqual(6); // V
expect(graph.size()[1]).toEqual(7); // E
expect(graph.toString()).toBe(
StringUtil.dontIndent`digraph G {
"app.R[R0]"->"app.R[R1]"->"app.R[R4]"->"app.R[R3]"->"app.R[R5]";
"app.R[R0]"->"app.R[R4]";
"app.R[R1]"->"app.R[R2]"->"app.R[R3]";
}`
StringUtil.dontIndent
lhstrh marked this conversation as resolved.
Show resolved Hide resolved
`graph
0["app.R[R3]"]
1["app.R[R5]"]
2["app.R[R4]"]
3["app.R[R2]"]
4["app.R[R1]"]
5["app.R[R0]"]
1 --> 0
0 --> 2
0 --> 3
3 --> 4
2 --> 4
4 --> 5
2 --> 5`
);
});

Expand All @@ -119,11 +129,19 @@ describe("Manually constructed precedence graphs", () => {
expect(graph.size()[0]).toEqual(6); // V
expect(graph.size()[1]).toEqual(6); // E
expect(graph.toString()).toBe(
`digraph G {
"app.R[R0]"->"app.R[R1]"->"app.R[R2]"->"app.R[R3]"->"app.R[R5]";
"app.R[R1]"->"app.R[R4]";
"app.R[R0]"->"app.R[R4]";
}`
StringUtil.dontIndent`graph
0["app.R[R3]"]
1["app.R[R5]"]
2["app.R[R4]"]
3["app.R[R2]"]
4["app.R[R1]"]
5["app.R[R0]"]
1 --> 0
0 --> 3
3 --> 4
2 --> 4
4 --> 5
2 --> 5`
);
});

Expand All @@ -133,25 +151,37 @@ describe("Manually constructed precedence graphs", () => {
expect(graph.size()[1]).toEqual(3); // E
Log.global.debug(graph.toString());
expect(graph.toString()).toBe(
StringUtil.dontIndent`digraph G {
"app.R[R2]"->"app.R[R3]"->"app.R[R5]";
"app.R[R0]"->"app.R[R4]";
}`
StringUtil.dontIndent`graph
0["app.R[R3]"]
1["app.R[R5]"]
2["app.R[R4]"]
3["app.R[R2]"]
4["app.R[R0]"]
1 --> 0
0 --> 3
2 --> 4`
);
});

it("add node 7, make 3 dependent on it", () => {
graph.addNode(nodes[6]);
graph.addEdges(nodes[2], new Set([nodes[6], nodes[3]]));
graph.addEdge(nodes[2], nodes[6]);
graph.addEdge(nodes[2], nodes[3]);
expect(graph.size()[0]).toEqual(6); // V
expect(graph.size()[1]).toEqual(4); // E
Log.global.debug(graph.toString());
expect(graph.toString()).toBe(
StringUtil.dontIndent`digraph G {
"app.R[R2]"->"app.R[R3]"->"app.R[R5]";
"app.R[R0]"->"app.R[R4]";
"app.R[R2]"->"app.R[R6]";
}`
StringUtil.dontIndent`graph
0["app.R[R3]"]
1["app.R[R5]"]
2["app.R[R4]"]
3["app.R[R2]"]
4["app.R[R0]"]
5["app.R[R6]"]
1 --> 0
0 --> 3
5 --> 3
2 --> 4`
);
});

Expand Down
41 changes: 22 additions & 19 deletions __tests__/graph.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ d2.addNode(node1);
d2.addNode(node2);
d2.addEdge(node1, node2);

test("test leafNodes() helper function", () => {
expect(d2.leafNodes()).toEqual(new Set([node1]));
test("test pureEffectNodes() helper function", () => {
expect(d2.pureEffectNodes()).toEqual(new Set([node1]));
});

test("test rootNodes() helper function", () => {
expect(d2.rootNodes()).toEqual(new Set([node2]));
test("test pureOriginNodes() helper function", () => {
expect(d2.pureOriginNodes()).toEqual(new Set([node2]));
});

const d3 = new DependencyGraph<number>();
Expand Down Expand Up @@ -136,15 +136,15 @@ const d7 = new DependencyGraph<number>();
const d8 = new DependencyGraph<number>();
const d9 = new DependencyGraph<number>();
test("test dependency graph", () => {
expect(d7.getEdges(node1).size).toBe(0);
expect(d7.getOriginsOfEffect(node1).size).toBe(0);
d7.merge(d5);
expect(d7.size()).toStrictEqual(d5.size());

d8.addNode(node1);
d9.addEdge(node1, node2);
d8.merge(d9);
expect(d8.size()).toStrictEqual(d9.size());
expect(d9.getBackEdges(node2).size).toBe(1);
expect(d9.getEffectsOfOrigin(node2).size).toBe(1);
d8.removeNode(node2);
expect(d8.size()).toStrictEqual([1, 0]);
});
Expand All @@ -154,13 +154,16 @@ test("test add/remove Edges", () => {
d10.addEdge(node1, node2); // {(node1 -> node2)}
expect(d10.size()).toStrictEqual([2, 1]);

d10.addBackEdges(node2, new Set<number>().add(node1).add(node3)); // {(node1 -> node2), (node3 -> node2)}
d10.addEdge(node1, node2);
d10.addEdge(node3, node2);
expect(d10.size()).toStrictEqual([3, 2]);

d10.addEdges(node1, new Set<number>().add(node2).add(node3).add(node4)); // {(node1 -> node2), (node1 -> node3), (node1 -> node4), (node3 -> node2)}
d10.addEdge(node1, node2);
d10.addEdge(node1, node3);
d10.addEdge(node1, node4);
expect(d10.size()).toStrictEqual([4, 4]);

d10.addEdges(node5, new Set<number>().add(node1)); // {(node1 -> node2), (node1 -> node3), (node1 -> node4), (node3 -> node2), {node5 -> node1}}
d10.addEdge(node5, node1);
expect(d10.size()).toStrictEqual([5, 5]);

d10.removeEdge(node1, node2); // {(node1 -> node3), (node1 -> node4), (node3 -> node2), {node5 -> node1}}
Expand All @@ -170,40 +173,40 @@ test("test add/remove Edges", () => {
const d11 = new DependencyGraph<number>();
const d12 = new DependencyGraph<Object>();
test("test the DOT representation of the dependency graph", () => {
expect(d11.toString()).toBe("digraph G {" + "\n}");
expect(d11.toDOTRepresentation()).toBe("digraph G {" + "\n}");

d11.addNode(node1); // { node1 }
expect(d11.toString()).toBe('digraph G {\n"1";\n}');
expect(d11.toDOTRepresentation()).toBe('digraph G {\n"1";\n}');

d11.addEdge(node1, node2); // { (node1 -> node2) }
d11.addEdge(node2, node3); // { (node1 -> node2 -> node3) }
expect(d11.toString()).toBe('digraph G {\n"1"->"2"->"3";\n}');
expect(d11.toDOTRepresentation()).toBe('digraph G {\n"1"->"2"->"3";\n}');

const obj = {0: 1};
d12.addNode(obj);
expect(d12.toString()).toBe('digraph G {\n"[object Object]";\n}');
expect(d12.toDOTRepresentation()).toBe('digraph G {\n"[object Object]";\n}');

d11.addEdge(node2, node1);
expect(d11.toString()).toBe('digraph G {\n"2"->"1"->"2"->"3";\n}');
expect(d11.toDOTRepresentation()).toBe('digraph G {\n"2"->"1"->"2"->"3";\n}');
d11.addEdge(node1, node3);
expect(d11.toString()).toBe('digraph G {\n"1"->"2"->"1"->"3";\n"2"->"3";\n}');
expect(d11.toDOTRepresentation()).toBe('digraph G {\n"1"->"2"->"1"->"3";\n"2"->"3";\n}');
});

const d13 = new DependencyGraph<number>();
test("test for reachableOrigins function of the dependency graph", () => {
d13.addEdge(node1, node2);
d13.addEdge(node1, node3);
d13.addEdge(node2, node4); // { (node1 -> node2 -> node4), (node1 -> node3) }
expect(d13.reachableOrigins(node1, new Set<number>(d13.nodes())).size).toBe(
expect(d13.reachableOrigins(node1, new Set<number>(d13.getNodes())).size).toBe(
3
);
expect(d13.reachableOrigins(node2, new Set<number>(d13.nodes())).size).toBe(
expect(d13.reachableOrigins(node2, new Set<number>(d13.getNodes())).size).toBe(
1
);
expect(d13.reachableOrigins(node3, new Set<number>(d13.nodes())).size).toBe(
expect(d13.reachableOrigins(node3, new Set<number>(d13.getNodes())).size).toBe(
0
);
expect(d13.reachableOrigins(node4, new Set<number>(d13.nodes())).size).toBe(
expect(d13.reachableOrigins(node4, new Set<number>(d13.getNodes())).size).toBe(
0
);
});
Expand Down
41 changes: 23 additions & 18 deletions __tests__/simple.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,12 @@ describe("Test names for contained reactors", () => {

it("graph before connect", () => {
expect(this._getPrecedenceGraph().toString()).toBe(
"digraph G {" +
"\n" +
'"myApp.x[M0]"->"myApp[M0]";' +
"\n" +
'"myApp.y[M0]"->"myApp[M0]";' +
"\n" +
"}"
StringUtil.dontIndent`graph
0["myApp.x[M0]"]
1["myApp[M0]"]
2["myApp.y[M0]"]
1 --> 0
1 --> 2`
);
});

Expand All @@ -92,23 +91,29 @@ describe("Test names for contained reactors", () => {

it("graph after connect and before disconnect", () => {
expect(this._getPrecedenceGraph().toString()).toBe(
StringUtil.dontIndent`digraph G {
"myApp.x.a"->"myApp.y.b";
"myApp.x[M0]"->"myApp[M0]";
"myApp.y[M0]"->"myApp[M0]";
}`
StringUtil.dontIndent`graph
0["myApp.x.a"]
1["myApp.y.b"]
2["myApp.x[M0]"]
3["myApp[M0]"]
4["myApp.y[M0]"]
1 --> 0
3 --> 2
3 --> 4`
);
});

it("graph after disconnect", () => {
this._disconnect(this.y.b, this.x.a);
expect(this._getPrecedenceGraph().toString()).toBe(
StringUtil.dontIndent`digraph G {
"myApp.x.a";
"myApp.y.b";
"myApp.x[M0]"->"myApp[M0]";
"myApp.y[M0]"->"myApp[M0]";
}`
StringUtil.dontIndent`graph
0["myApp.x.a"]
1["myApp.y.b"]
2["myApp.x[M0]"]
3["myApp[M0]"]
4["myApp.y[M0]"]
3 --> 2
3 --> 4`
);
});

Expand Down
Loading