import * as $G from "@/core/base/BaseGraph" ; import { DegreeDistribution , DegreeCentrality } from "@/centralities/Degree" ; import { JSONInput , IJSONInConfig } from "@/io/input/JSONInput" ; import { CSVInput , ICSVInConfig } from "@/io/input/CSVInput" ; import { SimplePerturber , NodeDegreeConfiguration } from "@/perturbation/SimplePerturbations" ; import { Logger } from "@/utils/Logger" ; import { GraphStats } from "@/core/interfaces" ; import { CSV_DATA_PATH , JSON_DATA_PATH } from "_/config/test_paths" ; const logger = new Logger ( ) ; const degCent = new DegreeCentrality ( ) ; const G_NR_NODES = 75 , G_NR_EDGES = 209 , test_graph = `${ JSON_DATA_PATH }/bernd_ares.json` ; let graph , json , stats , deg_config , PT ; const MAX_ADD_NODES = 100 , MAX_ADD_EDGES = 300 , MAX_DEG_PROB = 0.002 ; todo describe ( "GRAPH PERTURBATION TESTS: - " , ( ) => { describe ( "UNDIRECTED Graph - " , ( ) => { beforeEach ( ( ) => { json = new JSONInput ( ) ; graph = json . readFromJSONFile ( test_graph ) ; PT = new SimplePerturber ( graph ) ; stats = graph . stats ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; } ) ; describe ( "Randomly ADD different amounts / percentages of NODES - " , ( ) => { test ( "should refuse to add a negative AMOUNT of nodes" , ( ) => { expect ( ( ) => PT . addNodesAmount ( - 1 ) ) . toThrowError ( "Cowardly refusing to add a negative amount of nodes" ) ; } ) ; test ( "should refuse to add a negative PERCENTAGE of nodes" , ( ) => { expect ( ( ) => PT . addNodesPercentage ( - 1 ) ) . toThrowError ( "Cowardly refusing to add a negative amount of nodes" ) ; } ) ; it ( "should truncate number of nodes to add, if not integer" , ( ) => { const nrAddNodes = Math . random ( ) * 10 ; const rounded = Math . floor ( nrAddNodes ) ; PT . addNodesAmount ( nrAddNodes ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + rounded ) ; } ) ; test ( "should add a specified amount of nodes" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; PT . addNodesAmount ( nr_nodes_to_be_added ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES ) ; } ) ; test ( `should add some random percentage of nodes` , ( ) => { let p = Math . floor ( Math . random ( ) * 100 ) ; PT . addNodesPercentage ( p ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + Math . ceil ( ( G_NR_NODES * p ) / 100 ) ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES ) ; } ) ; test ( "should reject a negative node degree as invalid" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { und_degree : - 3 } ; expect ( PT . addNodesAmount . bind ( PT , nr_nodes_to_be_added , deg_config ) ) . toThrowError ( "Minimum degree cannot be negative." ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES ) ; } ) ; test ( "should reject a node degree greater than the amount of nodes" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; let one_too_many = G_NR_NODES + nr_nodes_to_be_added + 1 ; deg_config = { und_degree : one_too_many } ; expect ( PT . addNodesAmount . bind ( PT , nr_nodes_to_be_added , deg_config ) ) . toThrowError ( "Maximum degree exceeds number of reachable nodes." ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES ) ; } ) ; test ( "should add a specified amount of nodes with a regular degree of undirected edges" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { und_degree : 3 } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES + deg_config . und_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore a span of UNdirected edges to add when a specific degree is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { und_degree : 3 , min_und_degree : 2 , max_und_degree : 5 } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES + deg_config . und_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should add an amount of nodes within a specified degree span of UNdirected edges" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { min_und_degree : 3 , max_und_degree : 5 } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBeGreaterThanOrEqual ( G_NR_EDGES + deg_config . min_und_degree * nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBeLessThanOrEqual ( G_NR_EDGES + deg_config . max_und_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should add a specified amount of nodes with a regular degree of directed edges" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { dir_degree : 3 } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( deg_config . dir_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore a span of directed edges to add when a specific degree is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { dir_degree : 3 , min_dir_degree : 2 , max_dir_degree : 5 } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( deg_config . dir_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should add an amount of nodes within a specified degree span of directed edges" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { min_dir_degree : 2 , max_dir_degree : 5 } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBeGreaterThanOrEqual ( deg_config . min_dir_degree * nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBeLessThanOrEqual ( deg_config . max_dir_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore directed edge probabilities when a specific degree of directed edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { dir_degree : 3 , probability_dir : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( deg_config . dir_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore directed edge probabilities when a degree span of directed edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { min_dir_degree : 2 , max_dir_degree : 5 , probability_dir : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBeGreaterThanOrEqual ( deg_config . min_dir_degree * nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBeLessThanOrEqual ( deg_config . max_dir_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore directed edge probabilities when a specific degree of UNdirected edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { und_degree : 3 , probability_dir : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES + deg_config . und_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore directed edge probabilities when a degree span of UNdirected edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { min_und_degree : 2 , max_und_degree : 5 , probability_dir : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBeGreaterThanOrEqual ( G_NR_EDGES + deg_config . min_und_degree * nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBeLessThanOrEqual ( G_NR_EDGES + deg_config . max_und_degree * nr_nodes_to_be_added ) ; } ) ; description test ( "should create DIRECTED edges according to a given probability" , ( ) => { const nrAddNodes = Math . floor ( Math . random ( ) * MAX_ADD_NODES ) ; deg_config = { probability_dir : MAX_DEG_PROB } ; const nrOldNodes = graph . nrNodes ( ) ; PT . addNodesAmount ( nrAddNodes , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nrAddNodes ) ; expect ( graph . nrDirEdges ( ) ) . toBeGreaterThanOrEqual ( graph . nrDirEdges ( ) ) ; expect ( graph . nrDirEdges ( ) ) . toBeLessThanOrEqual ( graph . nrDirEdges ( ) + nrOldNodes * graph . nrNodes ( ) * MAX_DEG_PROB ) ; } ) ; test ( "should create UNdirected edges according to a given probability" , ( ) => { const nrAddNodes = Math . floor ( Math . random ( ) * MAX_ADD_NODES ) ; deg_config = { probability_und : MAX_DEG_PROB } ; const nrOldNodes = graph . nrNodes ( ) ; PT . addNodesAmount ( nrAddNodes , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nrAddNodes ) ; expect ( graph . nrUndEdges ( ) ) . toBeGreaterThanOrEqual ( graph . nrUndEdges ( ) ) ; expect ( graph . nrUndEdges ( ) ) . toBeLessThanOrEqual ( graph . nrUndEdges ( ) + nrOldNodes * graph . nrNodes ( ) * MAX_DEG_PROB ) ; } ) ; test ( "should ignore UNdirected edge probabilities when a specific degree of directed edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { dir_degree : 3 , probability_und : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( deg_config . dir_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore UNdirected edge probabilities when a degree span of directed edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { min_dir_degree : 2 , max_dir_degree : 5 , probability_und : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBeGreaterThanOrEqual ( deg_config . min_dir_degree * nr_nodes_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBeLessThanOrEqual ( deg_config . max_dir_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore UNdirected edge probabilities when a specific degree of UNdirected edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { und_degree : 3 , probability_und : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES + deg_config . und_degree * nr_nodes_to_be_added ) ; } ) ; test ( "should ignore UNdirected edge probabilities when a degree span of UNdirected edges is given" , ( ) => { let nr_nodes_to_be_added = Math . floor ( Math . random ( ) * G_NR_NODES ) ; deg_config = { min_und_degree : 2 , max_und_degree : 5 , probability_und : MAX_DEG_PROB } ; PT . addNodesAmount ( nr_nodes_to_be_added , deg_config ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES + nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBeGreaterThanOrEqual ( G_NR_EDGES + deg_config . min_und_degree * nr_nodes_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBeLessThanOrEqual ( G_NR_EDGES + deg_config . max_und_degree * nr_nodes_to_be_added ) ; } ) ; } ) ; describe ( "Randomly adding different amounts / percentages of UNDIRECTED edges" , ( ) => { test ( "should refuse to add a negative amount of UNdirected edges" , ( ) => { expect ( ( ) => PT . addEdgesAmount ( - 1 , { directed : false } ) ) . toThrowError ( "Cowardly refusing to add a non-positive amount of edges" ) ; } ) ; test ( "should refuse to add a negative percentage of UNdirected edges" , ( ) => { expect ( ( ) => PT . addUndEdgesPercentage ( - 1 ) ) . toThrowError ( "Cowardly refusing to add a non-positive amount of edges" ) ; } ) ; test ( "should add a specified amount of UNdirected edges" , ( ) => { let nr_und_edges_to_be_added = Math . floor ( Math . random ( ) * MAX_ADD_EDGES ) || 1 ; PT . addEdgesAmount ( nr_und_edges_to_be_added , { directed : false } ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES + nr_und_edges_to_be_added ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; } ) ; test ( "should add a specified percentage of UNdirected edges" , ( ) => { let percentage_und_edges_to_be_added = Math . random ( ) * 100 ; PT . addUndEdgesPercentage ( percentage_und_edges_to_be_added ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES + Math . ceil ( ( G_NR_EDGES * percentage_und_edges_to_be_added ) / 100 ) ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; } ) ; } ) ; todo describe ( "Randomly DELETE different amounts / percentages of NODES - " , ( ) => { test ( "should refuse to delete a negative AMOUNT of nodes" , ( ) => { expect ( ( ) => PT . deleteNodesAmount ( - 1 ) ) . toThrowError ( "Cowardly refusing to remove a negative amount of nodes" ) ; } ) ; test ( "should refuse to delete a negative PERCENTAGE of nodes" , ( ) => { expect ( ( ) => PT . deleteNodesPercentage ( - 1 ) ) . toThrowError ( "Cowardly refusing to remove a negative amount of nodes" ) ; } ) ; test ( "should simply delete all nodes when passing an amount greater than the number of existing nodes" , ( ) => { PT . deleteNodesAmount ( graph . nrNodes ( ) + 1 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrNodes ( ) ) . toBe ( 0 ) ; } ) ; test ( "should simply delete all nodes when passing a percentage greater than 100%" , ( ) => { PT . deleteNodesPercentage ( 101 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrNodes ( ) ) . toBe ( 0 ) ; } ) ; test ( "should delete a specified amount of nodes" , ( ) => { let nr_nodes_to_be_deleted = Math . floor ( Math . random ( ) * G_NR_NODES ) ; PT . deleteNodesAmount ( nr_nodes_to_be_deleted ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES - nr_nodes_to_be_deleted ) ; } ) ; test ( `should delete some random percentage of all nodes` , ( ) => { let p = Math . floor ( Math . random ( ) * 100 ) ; PT . deleteNodesPercentage ( p ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES - Math . ceil ( ( G_NR_NODES * p ) / 100 ) ) ; } ) ; } ) ; todo describe ( "Randomly delete different amounts / percentages of UNDIRECTED Edges - " , ( ) => { test ( "should refuse to delete a negative amount of edges" , ( ) => { expect ( PT . deleteUndEdgesAmount . bind ( PT , - 1 ) ) . toThrowError ( "Cowardly refusing to remove a negative amount of edges" ) ; } ) ; test ( "should refuse to delete a negative percentage of edges" , ( ) => { expect ( PT . deleteUndEdgesPercentage . bind ( PT , - 1 ) ) . toThrowError ( "Cowardly refusing to remove a negative amount of edges" ) ; } ) ; test ( "should simply delete all edges when passing an amount greater than the number of existing edges" , ( ) => { PT . deleteUndEdgesAmount ( 10e6 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; test ( "should simply delete all edges when passing a percentage greater than 100%" , ( ) => { PT . deleteUndEdgesPercentage ( 101 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; test ( "should delete a specified amount of edges" , ( ) => { let nr_edges_to_be_deleted = Math . floor ( Math . random ( ) * G_NR_EDGES ) ; PT . deleteUndEdgesAmount ( nr_edges_to_be_deleted ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES - nr_edges_to_be_deleted ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; test ( `should delete a random percentage of all edges` , ( ) => { let p = Math . floor ( Math . random ( ) * 100 ) ; PT . deleteUndEdgesPercentage ( p ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( G_NR_EDGES - Math . ceil ( ( G_NR_EDGES * p ) / 100 ) ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; } ) ; describe . skip ( "Adding different percentages of UNDIRECTED Edges - " , ( ) => { } ) ; } ) ; describe ( "DIRECTED Graph - " , ( ) => { beforeEach ( ( ) => { json = new JSONInput ( { explicit_direction : false , directed : true , weighted : false } ) ; graph = json . readFromJSONFile ( test_graph ) ; PT = new SimplePerturber ( graph ) ; stats = graph . getStats ( ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( G_NR_EDGES ) ; } ) ; /**
         * TODO: enhance by edge types
         */ describe ( "Randomly deleting different amounts / percentages of DIRECTED edges - " , ( ) => { test ( "should refuse to delete a negative amount of edges" , ( ) => { expect ( PT . deleteDirEdgesAmount . bind ( PT , - 1 ) ) . toThrowError ( "Cowardly refusing to remove a negative amount of edges" ) ; } ) ; test ( "should refuse to delete a negative percentage of edges" , ( ) => { expect ( PT . deleteDirEdgesPercentage . bind ( PT , - 1 ) ) . toThrowError ( "Cowardly refusing to remove a negative amount of edges" ) ; } ) ; test ( "should simply delete all edges when passing an amount greater than the number of existing edges" , ( ) => { PT . deleteDirEdgesAmount ( 10e6 ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; test ( "should simply delete all edges when passing a percentage greater than 100%" , ( ) => { PT . deleteDirEdgesPercentage ( 101 ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; test ( "should delete a specified amount of edges" , ( ) => { let nr_edges_to_be_deleted = Math . floor ( Math . random ( ) * G_NR_EDGES ) ; PT . deleteDirEdgesAmount ( nr_edges_to_be_deleted ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( G_NR_EDGES - nr_edges_to_be_deleted ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; test ( `should delete a certain percentage of all edges` , ( ) => { let p = Math . floor ( Math . random ( ) * 100 ) ; PT . deleteDirEdgesPercentage ( p ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( G_NR_EDGES - Math . ceil ( ( G_NR_EDGES * p ) / 100 ) ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; } ) ; } ) ; describe ( "Randomly adding different amounts / percentages of DIRECTED edges" , ( ) => { test ( "should refuse to add a negative amount of directed edges" , ( ) => { expect ( PT . addEdgesAmount . bind ( PT , - 1 , { directed : true } ) ) . toThrowError ( "Cowardly refusing to add a non-positive amount of edges" ) ; } ) ; test ( "should refuse to add a negative percentage of directed edges to an empty graph" , ( ) => { graph = new $G . BaseGraph ( "empty graph" ) ; expect ( PT . addDirEdgesPercentage . bind ( PT , - 1 , { directed : true } ) ) . toThrowError ( "Cowardly refusing to add a non-positive amount of edges" ) ; } ) ; test ( "should refuse to add a negative percentage of directed edges" , ( ) => { expect ( PT . addDirEdgesPercentage . bind ( PT , - 1 ) ) . toThrowError ( "Cowardly refusing to add a non-positive amount of edges" ) ; } ) ; test ( "should add a specified amount of directed edges" , ( ) => { let nr_dir_edges_to_be_added = Math . floor ( Math . random ( ) * MAX_ADD_EDGES ) || 1 ; PT . addEdgesAmount ( nr_dir_edges_to_be_added , { directed : true } ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( G_NR_EDGES + nr_dir_edges_to_be_added ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; } ) ; test ( "should add a specified percentage of directed edges" , ( ) => { let percentage_dir_edges_to_be_added = Math . random ( ) * 100 ; PT . addDirEdgesPercentage ( percentage_dir_edges_to_be_added ) ; expect ( graph . nrNodes ( ) ) . toBe ( G_NR_NODES ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( G_NR_EDGES + Math . ceil ( ( G_NR_EDGES * percentage_dir_edges_to_be_added ) / 100 ) ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; } ) ; } ) ; } ) ; /**
     * We don't know how to test RANDOM generation of something yet,
     * so we fall back to simply test differences in the degree distribution
     * This is a VERY WEAK test however, for even the addition or
     * deletion of a single edge would lead to the same result...
     * TODO figure out how to test this properly
     * PLUS - how to test for runtime ???
     */ describe ( "Randomly generate edges in an existing graph (create a random graph)" , ( ) => { let test_graph_file = `${ CSV_DATA_PATH }/small_graph_adj_list_def_sep.csv` , probability , min , max , deg_dist , graph , perturber , csv = new CSVInput ( ) ; beforeEach ( ( ) => { graph = csv . readFromAdjacencyListFile ( test_graph_file ) ; perturber = new SimplePerturber ( graph ) ; } ) ; describe ( "Random edge generation via probability" , ( ) => { test ( "should throw an error if probability is smaller 0" , ( ) => { probability = - 1 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( perturber . createEdgesProb . bind ( graph , probability , true ) ) . toThrowError ( "Probability out of range" ) ; } ) ; test ( "should throw an error if probability is greater 1" , ( ) => { probability = 2 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( perturber . createEdgesProb . bind ( graph , probability , true ) ) . toThrowError ( "Probability out of range" ) ; } ) ; test ( "DIRECTED - should randomly generate directed edges" , ( ) => { probability = 0.5 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; perturber . createEdgesProb ( probability , true ) ; expect ( graph . nrDirEdges ( ) ) . not . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( degCent . degreeDistribution ( graph ) ) . not . toEqual ( deg_dist ) ; } ) ; test ( "UNDIRECTED - should randomly generate UNdirected edges" , ( ) => { probability = 0.5 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; perturber . createEdgesProb ( probability , false ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . not . toBe ( 0 ) ; expect ( degCent . degreeDistribution ( graph ) ) . not . toEqual ( deg_dist ) ; } ) ; test ( "UNDIRECTED - should default to UNdirected edges if no direction is provided" , ( ) => { probability = 0.5 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; perturber . createEdgesProb ( probability ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . not . toBe ( 0 ) ; expect ( degCent . degreeDistribution ( graph ) ) . not . toEqual ( deg_dist ) ; } ) ; } ) ; /**
         * Although we clearly specify min / max in this case,
         * we can still not test for specific node degree (ranges),
         * except for the general fact that a nodes degree
         * should be in the range [0, max+n-1], as
         * all n-1 other nodes might have an edge to that node
         */ describe ( "Random edge generation via min / max #edges per node" , ( ) => { test ( "should throw an error if min is smaller 0" , ( ) => { min = - 1 ; max = 10 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( perturber . createEdgesSpan . bind ( perturber , min , max ) ) . toThrowError ( "Minimum degree cannot be negative." ) ; } ) ; test ( "should throw an error if max is greater (n-1)" , ( ) => { min = 0 ; max = 4 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( perturber . createEdgesSpan . bind ( perturber , min , max ) ) . toThrowError ( "Maximum degree exceeds number of reachable nodes." ) ; } ) ; test ( "should throw an error if max is greater (n-1)" , ( ) => { min = 4 ; max = 2 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( perturber . createEdgesSpan . bind ( perturber , min , max ) ) . toThrowError ( "Minimum degree cannot exceed maximum degree." ) ; } ) ; test ( "DIRECTED - should randomly generate directed edges" , ( ) => { min = 1 ; max = 3 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; perturber . createEdgesSpan ( min , max , true ) ; expect ( graph . nrDirEdges ( ) ) . not . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; expect ( degCent . degreeDistribution ( graph ) ) . not . toEqual ( deg_dist ) ; } ) ; test ( "UNDIRECTED - should randomly generate UNdirected edges" , ( ) => { min = 1 ; max = 3 ; deg_dist = degCent . degreeDistribution ( graph ) ; graph . clearAllEdges ( ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . toBe ( 0 ) ; perturber . createEdgesSpan ( min , max , false ) ; expect ( graph . nrDirEdges ( ) ) . toBe ( 0 ) ; expect ( graph . nrUndEdges ( ) ) . not . toBe ( 0 ) ; expect ( degCent . degreeDistribution ( graph ) ) . not . toEqual ( deg_dist ) ; } ) ; } ) ; } ) ; } ) ;