Skip to content

Commit

Permalink
Merge branch 'cycle/quad-edge-pair'
Browse files Browse the repository at this point in the history
  • Loading branch information
rodigu committed Apr 5, 2022
2 parents fbad429 + 793d736 commit 6ff495c
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 34 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
- [NeTS](#nets)
- [Basic Functionality](#basic-functionality)
- [Extra functionality](#extra-functionality)
- [Quadruplets](#quadruplets)

## NeTS

Expand Down Expand Up @@ -59,3 +60,9 @@ const net = await loadAdtacencyMatrix("file_name.csv");

For testing, you can use the `randomNetworkGen` function.
It randomly generates a network with the given arguments.

## Quadruplets

The quadruplets algorithm has the same exponetial time complexity as
the edge pair algorithm.
However, the less dense the network, the faster the quadruplets algorithm can get.
41 changes: 31 additions & 10 deletions algorithms.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Network } from "./network.ts";
import { ParsedCSV, base_id } from "./enums.ts";
import { ParsedCSV, base_id, NetworkArgs } from "./enums.ts";

/**
* Tries to generate a network with the given number of nodes and edges.
Expand All @@ -9,7 +9,7 @@ import { ParsedCSV, base_id } from "./enums.ts";
* @param {boolean} [args.is_directed]
* @returns Network
*/
export function randomNetworkGen(args: {
export function genRandomNetwork(args: {
number_vertices: number;
number_edges: number;
is_directed?: boolean;
Expand All @@ -22,21 +22,42 @@ export function randomNetworkGen(args: {
for (let vertex = 0; vertex < number_vertices; vertex++)
net.addVertex({ id: vertex });

args.edge_tries ??= 20;
while (net.edges.size < number_edges && args.edge_tries > 0) {
let edge_tries = args.edge_tries ?? 30;
while (net.edges.size < number_edges && edge_tries > 0) {
const from = Math.floor(Math.random() * number_vertices);
const to = Math.floor(Math.random() * number_vertices);
try {
net.addEdge({ from, to, do_force: false });
} catch (e) {
args.edge_tries--;
console.log(e.message);
}
if (from !== to && net.addEdge({ from, to, do_force: false }))
edge_tries = args.edge_tries ?? 30;

edge_tries--;
}

return net;
}

export function genCompleteNetwork(
size: number,
args: NetworkArgs = {}
): Network {
const complete_net = new Network(
Object.assign(args, {
vertex_limit: size,
edge_limit: Math.floor((size * (size - 1)) / 2),
})
);

for (let vertex = 0; vertex < size; vertex++) {
complete_net.addVertex({ id: vertex });
complete_net.vertices.forEach((v) => {
if (v.id !== vertex) {
complete_net.addEdge({ from: v.id, to: vertex });
}
});
}

return complete_net;
}

/**
* Reads an [adjacency matrix](https://www.wikiwand.com/en/Adjacency_matrix) CSV and returns a network object.
* @param {string} file_name
Expand Down
5 changes: 3 additions & 2 deletions network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export class Network {
/**
* @param {EdgeArgs} args
*/
addEdge(args: EdgeArgs) {
addEdge(args: EdgeArgs): boolean {
args.do_force ??= true;
args.weight ??= 1;

Expand All @@ -203,12 +203,13 @@ export class Network {
if (!this.vertices.has(args.to)) this.addVertex({ id: args.to });
}

if (!this.is_multigraph && this.hasEdge(args.from, args.to)) return;
if (!this.is_multigraph && this.hasEdge(args.from, args.to)) return false;
// throw { message: ERROR.NOT_MULTIGRAPH };

if (!this.is_directed) [args.from, args.to] = [args.from, args.to].sort();

this.edges.set(args.id, new Edge(args));
return true;
}

/**
Expand Down
168 changes: 146 additions & 22 deletions tester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,35 +81,159 @@ function getTestTime(): string {
);
}

const net_csv = await nex.loadAdjacencyMatrix("./data/networkMatrix.csv");
async function quadrupletsAdjacencyMatrixTimeTesting() {
const net_csv = await nex.loadAdjacencyMatrix(
"./data/FTXAdjacencyMatrix.csv"
);

// let test_data = valuesTest(net_csv) + "\n" + algorithmTest(net_csv);
let algo_start = Date.now();
const quad_csv_pair = net_csv.quadrupletsEdgePairing();
const pair_time = (Date.now() - algo_start) / 1000;
console.log("Edge pairing time taken:", pair_time);
console.log("Edge pairing size:", quad_csv_pair.length);
console.log("----------");
algo_start = Date.now();
const quad = net_csv.quadruplets();
const quad_time = (Date.now() - algo_start) / 1000;
// console.log(quad_csv_pair.map((c) => [...c.simple_edge_list]));
console.log("Quadruplets time taken:", quad_time);
console.log("Quad size:", quad.length);
}

// const end_time = new Date().getTime();
// const elapsed_time = (end_time - start_time) / 1000;
async function mainTest() {
const net_csv = await nex.loadAdjacencyMatrix(
"./data/FTXAdjacencyMatrix.csv"
);
let test_data = valuesTest(net_csv) + "\n" + algorithmTest(net_csv);
const end_time = new Date().getTime();
const elapsed_time = (end_time - start_time) / 1000;
test_data += "\nElapsed time: " + elapsed_time;
Deno.writeTextFile(
`./data/test_${getTestTime()}_${Math.floor(200 * Math.random())}.txt`,
test_data
);
}

// test_data += "\nElapsed time: " + elapsed_time;
function compareQuadAlgorithms(net: nets.Network, debug = false) {
let start = Date.now();

// Deno.writeTextFile(
// `./data/test_${getTestTime()}_${Math.floor(200 * Math.random())}.txt`,
// test_data
// );
const quad = net.quadruplets();
const quad_time = (Date.now() - start) / 1000;

const randomNet = nex.randomNetworkGen({
number_vertices: 6,
number_edges: 10,
});
start = Date.now();
const quad_pair = net.quadrupletsEdgePairing();
const quad_pair_time = (Date.now() - start) / 1000;

// nex.writeAdjacencyMatrix(randomNet);
if (debug) {
console.log("Quad algorithm");
console.log(quad.length);
console.log("Time taken: ", quad_time);

const quad_time = Date.now();
console.log("------");

console.log("Edge pairing algorithm");
console.log(quad_pair.length);
console.log("Time taken: ", quad_pair_time);
}

return [quad_time, quad_pair_time];
}

function getQuadTime(net: nets.Network): number {
const start = Date.now();
net.quadruplets();
return (Date.now() - start) / 1000;
}
function getPairTime(net: nets.Network): number {
const start = Date.now();
net.quadrupletsEdgePairing();
return (Date.now() - start) / 1000;
}

const quad = randomNet.quadruplets();
function quadEfficiencyTest(num = 20) {
const quad_data: number[] = [];
for (let n = 4; n < num; n++) {
console.log(n);
const complete_net = nex.genCompleteNetwork(n);
quad_data.push(getQuadTime(complete_net));
}

nex.writeAdjacencyMatrix(randomNet, "test_random_quad.csv");
Deno.writeTextFile(`./data/quad_data.json`, JSON.stringify(quad_data));
}

function pairEfficiencyTest(num = 20) {
const quad_data: number[] = [];
for (let n = 4; n < num; n++) {
console.log(n);
const complete_net = nex.genCompleteNetwork(n);
quad_data.push(getPairTime(complete_net));
}

Deno.writeTextFile(`./data/quad_pair_data.json`, JSON.stringify(quad_data));
}

function randomNetEfficiencyTest(
number_vertices = 20,
edges_num = { min: 10, max: 50 },
name = `random_efficiency_test.json`
) {
const quad: number[] = [];
const pair: number[] = [];
const net_list: number[] = [];

for (
let number_edges = edges_num.min;
number_edges < edges_num.max;
number_edges++
) {
console.log(number_edges);
const net = nex.genRandomNetwork({ number_vertices, number_edges });

if (!net_list.includes(net.edges.size)) {
quad.push(getQuadTime(net));
pair.push(getPairTime(net));

net_list.push(net.edges.size);
}
}

Deno.writeTextFile(
`./data/${name}`,
JSON.stringify({ quad, pair, number_vertices, net_list })
);
}

function quadrupletsEfficiencyTest(num = 20) {
quadEfficiencyTest(num);
pairEfficiencyTest(num);
}

function generalTesting() {
// const test_net = new nets.Network();
// try {
// test_net.addEdgeList([
// [1, 0],
// [1, 2],
// [1, 3],
// [1, 4],
// [1, 5],
// [0, 6],
// [0, 7],
// [1, 8],
// [6, 7],
// [2, 5],
// [5, 4],
// [3, 8],
// [4, 3],
// ]);
// } catch (e) {
// console.log(e);
// }
// const random_net = nex.genRandomNetwork({
// number_vertices: 15,
// number_edges: 20,
// });
}

console.log(
quad.map((c) => [...c.edges.values()]),
quad.length,
randomNet.edges
);
// compareQuadAlgorithms(nex.genCompleteNetwork(10), true);
randomNetEfficiencyTest(20, { min: 20, max: 120 }, "rand_dense.json");

0 comments on commit 6ff495c

Please sign in to comment.