diff --git a/libs/common/src/app/graph/algorithms/graph.has-cycle.spec.ts b/libs/common/src/app/graph/algorithms/graph.has-cycle.spec.ts new file mode 100644 index 00000000..1d7643b6 --- /dev/null +++ b/libs/common/src/app/graph/algorithms/graph.has-cycle.spec.ts @@ -0,0 +1,87 @@ +import { graphHasCycle } from "./graph.has-cycle"; +import { AdjacencyListTransformationParams, getAdjacencyList } from "../transformations"; + +describe("graphHasCycle", () => { + it("should not have a cycle", () => { + const graphs: AdjacencyListTransformationParams[] = [ + // "Empty" graphs + { arcs: [], nodes: [] }, + { + arcs: [], + nodes: [ + { inputs: [], outputs: [] }, + { inputs: [], outputs: [] } + ] + }, + { + arcs: [], + nodes: [ + { inputs: [{ _id: 1 }], outputs: [{ _id: 2 }] }, + { inputs: [{ _id: 3 }], outputs: [{ _id: 4 }] } + ] + }, + + { + arcs: [{ __from: 1, __to: 2 }], + nodes: [ + { inputs: [], outputs: [{ _id: 1 }] }, + { inputs: [{ _id: 2 }], outputs: [] } + ] + }, + { + arcs: [ + { __from: 11, __to: 20 }, + { __from: 11, __to: 21 }, + { __from: 11, __to: 30 }, + { __from: 22, __to: 31 } + ], + nodes: [ + { inputs: [{ _id: 10 }], outputs: [{ _id: 11 }] }, + { inputs: [{ _id: 20 }, { _id: 21 }], outputs: [{ _id: 22 }] }, + { inputs: [{ _id: 30 }, { _id: 31 }], outputs: [] } + ] + } + ]; + + for (const graph of graphs) { + expect(graphHasCycle(getAdjacencyList(graph))).toBeFalse(); + } + }); + + it("should have a cycle", () => { + const graphs: AdjacencyListTransformationParams[] = [ + { + arcs: [{ __from: 2, __to: 1 }], + nodes: [{ inputs: [{ _id: 1 }], outputs: [{ _id: 2 }] }] + }, + { + arcs: [ + { __from: 11, __to: 20 }, + { __from: 21, __to: 10 } + ], + nodes: [ + { inputs: [{ _id: 10 }], outputs: [{ _id: 11 }] }, + { inputs: [{ _id: 20 }], outputs: [{ _id: 21 }] } + ] + }, + { + arcs: [ + { __from: 11, __to: 20 }, + { __from: 11, __to: 30 }, + { __from: 22, __to: 30 }, + { __from: 22, __to: 31 }, + { __from: 32, __to: 10 } + ], + nodes: [ + { inputs: [{ _id: 10 }], outputs: [{ _id: 11 }] }, + { inputs: [{ _id: 20 }], outputs: [{ _id: 22 }] }, + { inputs: [{ _id: 30 }, { _id: 31 }], outputs: [{ _id: 32 }] } + ] + } + ]; + + for (const graph of graphs) { + expect(graphHasCycle(getAdjacencyList(graph))).toBeTrue(); + } + }); +}); diff --git a/libs/common/src/app/graph/algorithms/graph.has-cycle.ts b/libs/common/src/app/graph/algorithms/graph.has-cycle.ts new file mode 100644 index 00000000..3a390f62 --- /dev/null +++ b/libs/common/src/app/graph/algorithms/graph.has-cycle.ts @@ -0,0 +1,13 @@ +import { AdjacencyList } from "../transformations"; + +/** + * Detects if the given graph has a cycle. + * + * The cycle is determined by the explored nodes. + * + * @param graph the graph by its adjacency list + * @returns true if the graphs contains at least one cycle + */ +export function graphHasCycle(graph: AdjacencyList): boolean { + throw new Error("TODO"); +} diff --git a/libs/common/src/app/graph/algorithms/index.ts b/libs/common/src/app/graph/algorithms/index.ts new file mode 100644 index 00000000..1733d877 --- /dev/null +++ b/libs/common/src/app/graph/algorithms/index.ts @@ -0,0 +1 @@ +export * from "./graph.has-cycle"; diff --git a/libs/common/src/app/graph/transformations/get-adjacency.list.ts b/libs/common/src/app/graph/transformations/get-adjacency.list.ts index b5a70bd3..a02b2a56 100644 --- a/libs/common/src/app/graph/transformations/get-adjacency.list.ts +++ b/libs/common/src/app/graph/transformations/get-adjacency.list.ts @@ -74,6 +74,16 @@ export interface AdjacencyListItem = ReadonlyMap>; + /** * Gets the adjacency list from the arcs and the nodes of a graph * @@ -83,7 +93,7 @@ export interface AdjacencyListItem( params: AdjacencyListTransformationParams -): ReadonlyMap> { +): AdjacencyList { const { arcs, nodes } = params; // TODO: If the data becomes too big, transform to a non-functional approach