From 2e76b07551d5bc2820b3e9e2609d922d6e1d84b6 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 17:42:41 -0700 Subject: [PATCH 01/21] :sparkles: - got started with cycle class --- cycle.ts | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 cycle.ts diff --git a/cycle.ts b/cycle.ts new file mode 100644 index 0000000..00f4aac --- /dev/null +++ b/cycle.ts @@ -0,0 +1,53 @@ +import { Network } from "./network.ts"; +import { base_id, EdgeArgs } from "./enums.ts"; + +export class Cycle extends Network { + readonly loop_vertex: base_id; + private tip_vertex: base_id; + private is_closed: boolean; + + constructor(args: { is_directed: boolean; initial_edge: EdgeArgs }) { + super(args); + super.addEdge(args.initial_edge); + this.loop_vertex = args.initial_edge.from; + this.tip_vertex = args.initial_edge.to; + this.is_closed = false; + } + + get is_complete() { + return this.is_closed; + } + + addEdge(edge: EdgeArgs) { + if ( + !this.is_closed && + ((edge.from === this.tip_vertex && !this.hasVertex(edge.to)) || + (!this.is_directed && + edge.to === this.tip_vertex && + !this.hasVertex(edge.from))) + ) { + super.addEdge(edge); + this.tip_vertex = edge.to; + if (!this.is_directed && this.tip_vertex === edge.to) + this.tip_vertex = edge.from; + return true; + } + return false; + } + + close(edge: EdgeArgs) { + if ( + !this.is_closed && + ((edge.from === this.tip_vertex && edge.to === this.loop_vertex) || + (!this.is_directed && + edge.to === this.tip_vertex && + edge.from === this.loop_vertex)) + ) { + super.addEdge(edge); + this.is_closed = true; + this.tip_vertex = this.loop_vertex; + return true; + } + return false; + } +} From 9381e623523946b655f5214d66d686ff9c554fe7 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 17:45:54 -0700 Subject: [PATCH 02/21] :sparkles: - new edge features - restarted quadruplets --- edge.ts | 15 ++++++++++ network.ts | 88 +++++++++++++++++++++--------------------------------- 2 files changed, 49 insertions(+), 54 deletions(-) diff --git a/edge.ts b/edge.ts index 6dca9f8..e92813e 100644 --- a/edge.ts +++ b/edge.ts @@ -29,6 +29,21 @@ export class Edge { return { from: this.from, to: this.to, weight: this.weight }; } + isSameAs(edge: Edge, is_directed = false): boolean { + const { vertices } = this; + return ( + (edge.vertices.from === vertices.from && + edge.vertices.to === vertices.to) || + (!is_directed && + edge.vertices.from === vertices.to && + edge.vertices.to === vertices.from) + ); + } + + pairEdge(vertex_id: base_id): base_id { + return vertex_id === this.to ? this.from : this.to; + } + hasVertex(vertex_id: base_id): boolean { if (this.from === vertex_id || this.to === vertex_id) return true; return false; diff --git a/network.ts b/network.ts index f3c67a8..4118bca 100644 --- a/network.ts +++ b/network.ts @@ -6,7 +6,6 @@ import { EdgeArgs, NetworkArgs, ERROR, - Cycle, EdgeNeighborhood, } from "./enums.ts"; @@ -347,6 +346,15 @@ export class Network { return this.vertices.has(id); } + /** + * Returns true if an edge with the given id exists + * @param {base_id} id + * @returns boolean + */ + hasVertices(ids: base_id[]): boolean { + return ids.every((id) => this.vertices.has(id)); + } + /** * Get in-neighbors of a given vertex. * @@ -647,8 +655,8 @@ export class Network { * Returns a list with all triplets in the network. * @returns Cycle[] */ - triplets(): Cycle[] { - const triplet_list: Cycle[] = []; + triplets(): base_id[][] { + const triplet_list: base_id[][] = []; const k2 = this.core(2); @@ -658,7 +666,7 @@ export class Network { const { from, to } = edge.vertices; k2.neighbors(from).forEach((id) => { if (edge.hasVertex(id)) return; - const triplet: Cycle = [id, from, to]; + const triplet: base_id[] = [id, from, to]; const unsorted = [...triplet]; if ( @@ -674,64 +682,36 @@ export class Network { return triplet_list; } - quadruplets(): Cycle[] { - const c4: Cycle[] = []; + quadruplets(): base_id[][] { + const c4: base_id[][] = []; const k2 = this.core(2); - const { edges } = k2; - - edges.forEach((edge1) => { - const neighbors1 = this.edgeNeighbors(edge1); - const vertex_check: Map = new Map(); + const edges1 = k2.edges; - let small_neighborhood = neighbors1.from.neighbors; - vertex_check.set(neighbors1.from.id, 0); - vertex_check.set(neighbors1.to.id, 1); - - if (!this.is_directed) { - if (neighbors1.from.neighbors.length > neighbors1.to.neighbors.length) { - vertex_check.set(neighbors1.to.id, 0); - vertex_check.set(neighbors1.from.id, 1); - small_neighborhood = neighbors1.to.neighbors; - } - } - - small_neighborhood.forEach((vertex_id) => { - const edges_of = this.is_directed - ? this.edgesFrom(vertex_id) - : this.edgesWith(vertex_id); - if (!vertex_check.has(vertex_id)) { - vertex_check.set(vertex_id, 2); - edges_of.forEach((edge2) => { - const { vertices } = edge2; - vertex_check.set( - vertices.from === vertex_id ? vertices.to : vertices.from, - 3 - ); - - const check_list = [...vertex_check.keys()]; - if ( - this.hasEdge(check_list[3], check_list[0]) && - vertex_check.size === 4 && - !this.listHasCycle(c4, [...vertex_check.keys()]) - ) - c4.push([...vertex_check.keys()]); - }); - } - }); - }); + edges1.forEach((edge1) => {}); return c4; } - edgesFrom(vertex_id: base_id): Edge[] { - return this.edge_list.filter((edge) => edge.vertices.from === vertex_id); + /** + * Edges that start at vertex_id. Excluding edges with a `to` vertex in the `except` array + * @param {base_id} vertex_id + * @param {base_id[]=[]} except + * @returns Edge + */ + edgesFrom(vertex_id: base_id, except: base_id[] = []): Edge[] { + return this.edge_list.filter( + (edge) => + edge.vertices.from === vertex_id && !except.includes(edge.vertices.to) + ); } - edgesWith(vertex_id: base_id): Edge[] { + edgesWith(vertex_id: base_id, except: base_id[]): Edge[] { return this.edge_list.filter( (edge) => - edge.vertices.from === vertex_id || edge.vertices.to === vertex_id + (edge.vertices.from === vertex_id || edge.vertices.to === vertex_id) && + (!except.includes(edge.vertices.to) || + !except.includes(edge.vertices.from)) ); } @@ -763,7 +743,7 @@ export class Network { * @param {Cycle} triplet * @returns boolean */ - private listHasCycle(cycle_arr: Cycle[], cycle: Cycle): boolean { + private listHasCycle(cycle_arr: base_id[][], cycle: base_id[]): boolean { return cycle_arr.some((trip) => this.isSameCycle(cycle, trip)); } @@ -773,9 +753,9 @@ export class Network { * @param {Cycle} arr2 * @returns boolean */ - private isSameCycle(arr1: Cycle, arr2: Cycle): boolean { + private isSameCycle(arr1: base_id[], arr2: base_id[]): boolean { if (arr1.length !== arr2.length) return false; - return arr1.every((element, index) => element === arr2[index]); + return arr1.every((element) => arr2.includes(element)); } /** From 96672c11de4bba3e8d4eafef34c03008c78cf507 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 19:45:29 -0700 Subject: [PATCH 03/21] :truck: - removed cycle.ts - moved Cycle class to network.ts --- cycle.ts | 53 ------------------------------------------ network.ts | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 53 deletions(-) delete mode 100644 cycle.ts diff --git a/cycle.ts b/cycle.ts deleted file mode 100644 index 00f4aac..0000000 --- a/cycle.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Network } from "./network.ts"; -import { base_id, EdgeArgs } from "./enums.ts"; - -export class Cycle extends Network { - readonly loop_vertex: base_id; - private tip_vertex: base_id; - private is_closed: boolean; - - constructor(args: { is_directed: boolean; initial_edge: EdgeArgs }) { - super(args); - super.addEdge(args.initial_edge); - this.loop_vertex = args.initial_edge.from; - this.tip_vertex = args.initial_edge.to; - this.is_closed = false; - } - - get is_complete() { - return this.is_closed; - } - - addEdge(edge: EdgeArgs) { - if ( - !this.is_closed && - ((edge.from === this.tip_vertex && !this.hasVertex(edge.to)) || - (!this.is_directed && - edge.to === this.tip_vertex && - !this.hasVertex(edge.from))) - ) { - super.addEdge(edge); - this.tip_vertex = edge.to; - if (!this.is_directed && this.tip_vertex === edge.to) - this.tip_vertex = edge.from; - return true; - } - return false; - } - - close(edge: EdgeArgs) { - if ( - !this.is_closed && - ((edge.from === this.tip_vertex && edge.to === this.loop_vertex) || - (!this.is_directed && - edge.to === this.tip_vertex && - edge.from === this.loop_vertex)) - ) { - super.addEdge(edge); - this.is_closed = true; - this.tip_vertex = this.loop_vertex; - return true; - } - return false; - } -} diff --git a/network.ts b/network.ts index 4118bca..6eb12d7 100644 --- a/network.ts +++ b/network.ts @@ -792,3 +792,70 @@ export class Network { return false; } } + +export class Cycle extends Network { + readonly loop_vertex: base_id; + private tip_vertex: base_id; + private is_closed: boolean; + + constructor(args: { + is_directed: boolean; + initial_edge: EdgeArgs; + loop_vertex?: base_id; + }) { + super(args); + const { initial_edge, loop_vertex, is_directed } = args; + super.addEdge(initial_edge); + this.loop_vertex = initial_edge.from; + this.tip_vertex = initial_edge.to; + if (!is_directed && loop_vertex !== undefined) { + this.loop_vertex = loop_vertex; + this.tip_vertex = this.edge_list[0].pairVertex(this.loop_vertex)!; + } + this.is_closed = false; + } + + get tip() { + return this.tip_vertex; + } + get is_complete() { + return this.is_closed; + } + + addEdge(edge: EdgeArgs | undefined) { + if ( + edge !== undefined && + !this.is_closed && + ((edge.from === this.tip_vertex && !this.hasVertex(edge.to)) || + (!this.is_directed && + edge.to === this.tip_vertex && + !this.hasVertex(edge.from))) + ) { + super.addEdge(edge); + this.tip_vertex = edge.to; + if (!this.is_directed && this.tip_vertex === edge.to) + this.tip_vertex = edge.from; + return true; + } + + return false; + } + + close(edge: EdgeArgs | undefined) { + if ( + edge !== undefined && + !this.is_closed && + ((edge.from === this.tip_vertex && edge.to === this.loop_vertex) || + (!this.is_directed && + edge.to === this.tip_vertex && + edge.from === this.loop_vertex)) + ) { + super.addEdge(edge); + this.is_closed = true; + this.tip_vertex = this.loop_vertex; + return true; + } + + return false; + } +} From 00cdf9438e22c2fbce89ebab3e3dac10dc724588 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 19:46:00 -0700 Subject: [PATCH 04/21] :bug: With edgesWith() --- network.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/network.ts b/network.ts index 6eb12d7..2f7c92f 100644 --- a/network.ts +++ b/network.ts @@ -706,12 +706,10 @@ export class Network { ); } - edgesWith(vertex_id: base_id, except: base_id[]): Edge[] { + edgesWith(vertex_id: base_id): Edge[] { return this.edge_list.filter( (edge) => - (edge.vertices.from === vertex_id || edge.vertices.to === vertex_id) && - (!except.includes(edge.vertices.to) || - !except.includes(edge.vertices.from)) + edge.vertices.from === vertex_id || edge.vertices.to === vertex_id ); } From 72b46c473191640c09e41a904b7c37be6185fd9e Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 19:46:39 -0700 Subject: [PATCH 05/21] :construction: Quadruplets algorithm --- network.ts | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/network.ts b/network.ts index 2f7c92f..3e14b7a 100644 --- a/network.ts +++ b/network.ts @@ -682,13 +682,51 @@ export class Network { return triplet_list; } - quadruplets(): base_id[][] { - const c4: base_id[][] = []; + quadruplets(): Cycle[] { + const c4: Cycle[] = []; const k2 = this.core(2); const edges1 = k2.edges; - edges1.forEach((edge1) => {}); + edges1.forEach((edge1) => { + const initial_edge = edge1.args; + let loop_vertex = edge1.vertices.from; + let pair_vertex = edge1.pairVertex(loop_vertex)!; + let pair_vertex_neighbors = k2.neighbors(pair_vertex); + + if (!k2.is_directed) { + const loop_vertex_neighbors = k2.neighbors(loop_vertex); + if (pair_vertex_neighbors.length > loop_vertex_neighbors.length) { + const temp = loop_vertex; + loop_vertex = pair_vertex; + pair_vertex = temp; + pair_vertex_neighbors = loop_vertex_neighbors; + } + } + + pair_vertex_neighbors.forEach((vertex) => { + const parallel_edges = k2.is_directed + ? k2.edgesFrom(vertex) + : k2.edgesWith(vertex); + + parallel_edges.forEach((p_edge) => { + const cycle = new Cycle({ + is_directed: k2.is_directed, + initial_edge, + loop_vertex, + }); + if (cycle.addEdge(k2.edgeBetween(cycle.tip, vertex)?.args)) + if (cycle.addEdge(p_edge.args)) + if ( + cycle.close( + k2.edgeBetween(p_edge.pairVertex(cycle.tip), loop_vertex) + ?.args + ) + ) + c4.push(cycle); + }); + }); + }); return c4; } From cf145dc05c13bdd6cdc43099700994e60a3e3fec Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 19:48:02 -0700 Subject: [PATCH 06/21] :memo: pairVertex function name - changed from pairEdge --- edge.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/edge.ts b/edge.ts index e92813e..a91e58d 100644 --- a/edge.ts +++ b/edge.ts @@ -40,8 +40,10 @@ export class Edge { ); } - pairEdge(vertex_id: base_id): base_id { - return vertex_id === this.to ? this.from : this.to; + pairVertex(vertex_id: base_id): base_id | undefined { + if (vertex_id === this.to) return this.from; + else if (vertex_id === this.from) return this.to; + return undefined; } hasVertex(vertex_id: base_id): boolean { From fe9bc21859b104aa741ca5ed6faddec379e9da8a Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 19:48:34 -0700 Subject: [PATCH 07/21] :bug: edgeBetween now handles undefined from and to --- network.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/network.ts b/network.ts index 3e14b7a..d7c465f 100644 --- a/network.ts +++ b/network.ts @@ -282,10 +282,11 @@ export class Network { * @returns base_id[] */ edgeBetween( - from: base_id, - to: base_id, + from: base_id | undefined, + to: base_id | undefined, is_directed = this.is_directed ): Edge | undefined { + if (from === undefined || to === undefined) return undefined; return this.edge_list.find(({ vertices }) => this.checkEdgeIsSame(vertices, { from, to }, is_directed) ); From 0b892404dcc4cdc0d6ef9fd3a69d1a77cfe08a90 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 19:48:55 -0700 Subject: [PATCH 08/21] :fire: cycle type --- enums.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/enums.ts b/enums.ts index 3590434..89bbfb2 100644 --- a/enums.ts +++ b/enums.ts @@ -1,7 +1,5 @@ export type base_id = string | number; -export type Cycle = base_id[]; - export interface EdgeNeighborhood { from: { id: base_id; From 38d51d9d5892aeaf9493b0e06e278646e91254a5 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sat, 2 Apr 2022 19:56:38 -0700 Subject: [PATCH 09/21] :children_crossing: Changed declaration order - from and to --- edge.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edge.ts b/edge.ts index a91e58d..dd3990f 100644 --- a/edge.ts +++ b/edge.ts @@ -1,8 +1,8 @@ import { base_id, EdgeArgs } from "./enums.ts"; export class Edge { - private to: base_id; private from: base_id; + private to: base_id; weight: number; /** From 3496ab55c0f9850d8be4faaa974a051ed100c0e7 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 09:02:08 -0700 Subject: [PATCH 10/21] :sparkles: compare cycles --- network.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/network.ts b/network.ts index d7c465f..7335b16 100644 --- a/network.ts +++ b/network.ts @@ -895,4 +895,17 @@ export class Cycle extends Network { return false; } + + isSameAs(cycle: Cycle) { + return this.edge_list.every(({ vertices }) => { + return cycle.edge_list.some(({ vertices: compare }) => { + return ( + (compare.from === vertices.from && compare.to === vertices.to) || + (!this.is_directed && + compare.from === vertices.to && + compare.to === vertices.from) + ); + }); + }); + } } From 20779eb3b51a079b3047dcde86ba84cb3864e173 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 09:03:12 -0700 Subject: [PATCH 11/21] :bug: cycle tip - cycle tip now added appropriately --- network.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network.ts b/network.ts index 7335b16..a59fc55 100644 --- a/network.ts +++ b/network.ts @@ -869,9 +869,10 @@ export class Cycle extends Network { !this.hasVertex(edge.from))) ) { super.addEdge(edge); - this.tip_vertex = edge.to; if (!this.is_directed && this.tip_vertex === edge.to) this.tip_vertex = edge.from; + else this.tip_vertex = edge.to; + return true; } From 0b50b7daa71c358e6ee7cd1ba27f822750ea393d Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 09:03:56 -0700 Subject: [PATCH 12/21] :bug: repeated c4 - quadruplets now won't output duplicated cycles --- network.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/network.ts b/network.ts index a59fc55..bc38a9c 100644 --- a/network.ts +++ b/network.ts @@ -716,15 +716,11 @@ export class Network { initial_edge, loop_vertex, }); + if (cycle.addEdge(k2.edgeBetween(cycle.tip, vertex)?.args)) if (cycle.addEdge(p_edge.args)) - if ( - cycle.close( - k2.edgeBetween(p_edge.pairVertex(cycle.tip), loop_vertex) - ?.args - ) - ) - c4.push(cycle); + if (cycle.close(k2.edgeBetween(cycle.tip, loop_vertex)?.args)) + if (!c4.some((c) => c.isSameAs(cycle))) c4.push(cycle); }); }); }); From 9ba299c4c332fc77a4deee748f25121b52c7a46b Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 11:46:08 -0700 Subject: [PATCH 13/21] :white_check_mark: time testing --- tester.ts | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/tester.ts b/tester.ts index 1ee7a45..22f2547 100644 --- a/tester.ts +++ b/tester.ts @@ -81,7 +81,7 @@ function getTestTime(): string { ); } -// const net_csv = await nex.loadAdjacencyMatrix("./data/networkMatrix.csv"); +const net_csv = await nex.loadAdjacencyMatrix("./data/networkMatrix.csv"); // let test_data = valuesTest(net_csv) + "\n" + algorithmTest(net_csv); @@ -95,22 +95,20 @@ function getTestTime(): string { // test_data // ); -// const randomNet = nex.randomNetworkGen({ -// number_vertices: 20, -// number_edges: 40, -// }); +const randomNet = nex.randomNetworkGen({ + number_vertices: 20, + number_edges: 40, +}); // nex.writeAdjacencyMatrix(randomNet); -const net = new nets.Network(); -net.addEdgeList([ - ["a", "b"], - ["b", "c"], - ["c", "d"], - ["d", "a"], - ["e", "d"], - ["e", "c"], - ["b", "d"], -]); - -console.log(net.quadruplets()); +const quad_time = Date.now(); + +const quad = randomNet.quadruplets(); + +console.log( + quad.map((c) => [...c.edges.values()]), + quad.length, + Date.now() - quad_time, + randomNet.edges +); From 797983a3bd9486cff1a63e2f523f6db9ae234692 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 12:25:06 -0700 Subject: [PATCH 14/21] :sparkles: simple edge list --- network.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/network.ts b/network.ts index bc38a9c..f6d86ac 100644 --- a/network.ts +++ b/network.ts @@ -135,6 +135,10 @@ export class Network { return [...this.edges.values()]; } + get simple_edge_list(): [base_id, base_id][] { + return this.edge_list.map(({ vertices }) => [vertices.from, vertices.to]); + } + /** * Number of edges in the [maximum clique possible](https://www.wikiwand.com/en/Clique_(graph_theory)) with the network's number of verices. * @returns number From 2d9fd73fd55b3d0d50b167fd9394094608450292 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 12:25:22 -0700 Subject: [PATCH 15/21] :bug: with self-loops --- network.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/network.ts b/network.ts index f6d86ac..e72b69b 100644 --- a/network.ts +++ b/network.ts @@ -181,6 +181,8 @@ export class Network { if (this.edges.has(args.id)) throw { message: ERROR.EXISTING_EDGE }; + if (args.from === args.to) throw { message: ERROR.SELF_LOOP, args }; + if (this.edges.size >= this.edge_limit) throw { message: ERROR.EDGE_LIMIT }; if (!args.do_force) { From 811f79d87c7e4ff3986898828b1c6565f022b05e Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 12:25:43 -0700 Subject: [PATCH 16/21] :goal_net: error for self-loops --- enums.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/enums.ts b/enums.ts index 89bbfb2..9f2c650 100644 --- a/enums.ts +++ b/enums.ts @@ -43,4 +43,5 @@ export const ERROR = { NOT_MULTIGRAPH: "Trying to add multiple edges between two vertices. Graph is not a multigraph!", UNDEFINED_ID: "Tried to use undefined id as input", + SELF_LOOP: "No self-loops", }; From 42d00fc32516b6ad94373603f5bd9efff76fba03 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 12:26:07 -0700 Subject: [PATCH 17/21] :white_check_mark: quad testing --- tester.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tester.ts b/tester.ts index 22f2547..3ecb823 100644 --- a/tester.ts +++ b/tester.ts @@ -96,8 +96,8 @@ const net_csv = await nex.loadAdjacencyMatrix("./data/networkMatrix.csv"); // ); const randomNet = nex.randomNetworkGen({ - number_vertices: 20, - number_edges: 40, + number_vertices: 6, + number_edges: 10, }); // nex.writeAdjacencyMatrix(randomNet); @@ -106,9 +106,10 @@ const quad_time = Date.now(); const quad = randomNet.quadruplets(); +nex.writeAdjacencyMatrix(randomNet, "test_random_quad.csv"); + console.log( quad.map((c) => [...c.edges.values()]), quad.length, - Date.now() - quad_time, randomNet.edges ); From 7f1f28ef8d5333540ffbad13af4c66687af42039 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 15:59:38 -0700 Subject: [PATCH 18/21] Added .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5fac628 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/data/ \ No newline at end of file From a573e1687f523594e758740876249d3265881f23 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 16:16:49 -0700 Subject: [PATCH 19/21] :memo: --- network.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/network.ts b/network.ts index e72b69b..9633834 100644 --- a/network.ts +++ b/network.ts @@ -131,10 +131,18 @@ export class Network { return [...this.vertices.values()]; } + /** + * Get an array with the edges of the network + * @returns Edge[] + */ get edge_list(): Edge[] { return [...this.edges.values()]; } + /** + * Returns pairs of nodes that represent `from` and `to` (respectively) vertices in an edge + * @returns [base_id, base_id][] + */ get simple_edge_list(): [base_id, base_id][] { return this.edge_list.map(({ vertices }) => [vertices.from, vertices.to]); } @@ -689,6 +697,10 @@ export class Network { return triplet_list; } + /** + * Algorithm to find all quadruplets in a network. + * @returns Cycle[] + */ quadruplets(): Cycle[] { const c4: Cycle[] = []; @@ -747,6 +759,11 @@ export class Network { ); } + /** + * Returns all edges with the given vertex, regardless of the position of the vertex (`from` or `to`). + * @param {base_id} vertex_id + * @returns Edge + */ edgesWith(vertex_id: base_id): Edge[] { return this.edge_list.filter( (edge) => @@ -754,6 +771,11 @@ export class Network { ); } + /** + * Returns the given edge's neighborhood. That is, the neighborhood of both its vertices. + * @param {Edge} edge + * @returns EdgeNeighborhood + */ edgeNeighbors(edge: Edge): EdgeNeighborhood { const { from, to } = edge.vertices; const edge_neighbors: EdgeNeighborhood = { From d9ab9b016dee33dc3a68a229d6394d5aa56904b6 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 16:18:34 -0700 Subject: [PATCH 20/21] :art: created can add and can close functions - help with organizing the code and readability - add and close functions now shorter --- network.ts | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/network.ts b/network.ts index 9633834..974cbed 100644 --- a/network.ts +++ b/network.ts @@ -883,15 +883,9 @@ export class Cycle extends Network { return this.is_closed; } - addEdge(edge: EdgeArgs | undefined) { - if ( - edge !== undefined && - !this.is_closed && - ((edge.from === this.tip_vertex && !this.hasVertex(edge.to)) || - (!this.is_directed && - edge.to === this.tip_vertex && - !this.hasVertex(edge.from))) - ) { + */ + addEdge(edge: EdgeArgs | undefined): boolean { + if (edge !== undefined && this.canAdd(edge)) { super.addEdge(edge); if (!this.is_directed && this.tip_vertex === edge.to) this.tip_vertex = edge.from; @@ -933,4 +927,24 @@ export class Cycle extends Network { }); }); } + + private canCloseWith(edge: EdgeArgs): boolean { + const edge_has_tip_and_loop_vertex = + (edge.from === this.tip_vertex && edge.to === this.loop_vertex) || + (!this.is_directed && + edge.to === this.tip_vertex && + edge.from === this.loop_vertex); + + return !this.is_closed && edge_has_tip_and_loop_vertex; + } + + private canAdd(edge: EdgeArgs) { + const edge_has_tip = + (edge.from === this.tip_vertex && !this.hasVertex(edge.to)) || + (!this.is_directed && + edge.to === this.tip_vertex && + !this.hasVertex(edge.from)); + + return !this.is_closed && edge_has_tip; + } } From 905de07ca14e3bc945bd2c193bb61eff21c84253 Mon Sep 17 00:00:00 2001 From: Rodrigo Morais <58960796+rodigu@users.noreply.github.com> Date: Sun, 3 Apr 2022 16:19:04 -0700 Subject: [PATCH 21/21] :memo: Cycle class documentation --- network.ts | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/network.ts b/network.ts index 974cbed..926aa98 100644 --- a/network.ts +++ b/network.ts @@ -876,13 +876,27 @@ export class Cycle extends Network { this.is_closed = false; } - get tip() { + /** + * Getter for the tip of the cycle. + * @returns base_id + */ + get tip(): base_id { return this.tip_vertex; } - get is_complete() { + + /** + * Returns true if the cycle is closed, otherwise returns false. + * @returns boolean + */ + get is_complete(): boolean { return this.is_closed; } + /** + * Adds an edge to the cycle if possible. + * Returns true if the addition is successful. + * @param {EdgeArgs|undefined} edge + * @returns boolean */ addEdge(edge: EdgeArgs | undefined): boolean { if (edge !== undefined && this.canAdd(edge)) { @@ -897,15 +911,14 @@ export class Cycle extends Network { return false; } - close(edge: EdgeArgs | undefined) { - if ( - edge !== undefined && - !this.is_closed && - ((edge.from === this.tip_vertex && edge.to === this.loop_vertex) || - (!this.is_directed && - edge.to === this.tip_vertex && - edge.from === this.loop_vertex)) - ) { + /** + * Tries to close the cycle. + * Returns true if the operation was sucessful. + * @param {EdgeArgs|undefined} edge + * @returns boolean + */ + close(edge: EdgeArgs | undefined): boolean { + if (edge !== undefined && this.canCloseWith(edge)) { super.addEdge(edge); this.is_closed = true; this.tip_vertex = this.loop_vertex; @@ -915,7 +928,14 @@ export class Cycle extends Network { return false; } - isSameAs(cycle: Cycle) { + /** + * Compares the cycle with a given cycle. + * Returns whether they are the same or not. + * @param {Cycle} cycle + * @returns boolean + */ + isSameAs(cycle: Cycle): boolean { + if (this.is_directed !== cycle.is_directed) return false; return this.edge_list.every(({ vertices }) => { return cycle.edge_list.some(({ vertices: compare }) => { return (