├── .gitignore ├── LICENSE ├── README.md ├── example.py ├── node2vec ├── __init__.py ├── check_gensim.py ├── edges.py ├── node2vec.py ├── parallel.py └── setup.cfg ├── poetry.lock └── pyproject.toml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled python modules. 2 | *.pyc 3 | 4 | # Setuptools distribution folder. 5 | /dist/ 6 | 7 | # Python egg metadata, regenerated from source files by setuptools. 8 | /*.egg-info 9 | 10 | .idea 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Elior Cohen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node2Vec 2 | [![Downloads](http://pepy.tech/badge/node2vec)](http://pepy.tech/project/node2vec) 3 | 4 | Python3 implementation of the node2vec algorithm Aditya Grover, Jure Leskovec and Vid Kocijan. 5 | [node2vec: Scalable Feature Learning for Networks. A. Grover, J. Leskovec. ACM SIGKDD International Conference on Knowledge Discovery and Data Mining (KDD), 2016.](https://snap.stanford.edu/node2vec/) 6 | 7 | # Maintenance 8 | 9 | ### I no longer have time to maintain this, if someone wants to pick the baton let me know 10 | 11 | ## Installation 12 | 13 | `pip install node2vec` 14 | 15 | ## Usage 16 | ```python 17 | import networkx as nx 18 | from node2vec import Node2Vec 19 | 20 | # Create a graph 21 | graph = nx.fast_gnp_random_graph(n=100, p=0.5) 22 | 23 | # Precompute probabilities and generate walks - **ON WINDOWS ONLY WORKS WITH workers=1** 24 | node2vec = Node2Vec(graph, dimensions=64, walk_length=30, num_walks=200, workers=4) # Use temp_folder for big graphs 25 | 26 | # Embed nodes 27 | model = node2vec.fit(window=10, min_count=1, batch_words=4) # Any keywords acceptable by gensim.Word2Vec can be passed, `dimensions` and `workers` are automatically passed (from the Node2Vec constructor) 28 | 29 | # Look for most similar nodes 30 | model.wv.most_similar('2') # Output node names are always strings 31 | 32 | # Save embeddings for later use 33 | model.wv.save_word2vec_format(EMBEDDING_FILENAME) 34 | 35 | # Save model for later use 36 | model.save(EMBEDDING_MODEL_FILENAME) 37 | 38 | # Embed edges using Hadamard method 39 | from node2vec.edges import HadamardEmbedder 40 | 41 | edges_embs = HadamardEmbedder(keyed_vectors=model.wv) 42 | 43 | # Look for embeddings on the fly - here we pass normal tuples 44 | edges_embs[('1', '2')] 45 | ''' OUTPUT 46 | array([ 5.75068220e-03, -1.10937878e-02, 3.76693785e-01, 2.69105062e-02, 47 | ... ... .... 48 | ..................................................................], 49 | dtype=float32) 50 | ''' 51 | 52 | # Get all edges in a separate KeyedVectors instance - use with caution could be huge for big networks 53 | edges_kv = edges_embs.as_keyed_vectors() 54 | 55 | # Look for most similar edges - this time tuples must be sorted and as str 56 | edges_kv.most_similar(str(('1', '2'))) 57 | 58 | # Save embeddings for later use 59 | edges_kv.save_word2vec_format(EDGES_EMBEDDING_FILENAME) 60 | 61 | ``` 62 | 63 | ### Parameters 64 | 65 | #### `node2vec.Node2vec` 66 | 67 | - `Node2Vec` constructor: 68 | 1. `graph`: The first positional argument has to be a networkx graph. Node names must be all integers or all strings. On the output model they will always be strings. 69 | 2. `dimensions`: Embedding dimensions (default: 128) 70 | 3. `walk_length`: Number of nodes in each walk (default: 80) 71 | 4. `num_walks`: Number of walks per node (default: 10) 72 | 5. `p`: Return hyper parameter (default: 1) 73 | 6. `q`: Input parameter (default: 1) 74 | 7. `weight_key`: On weighted graphs, this is the key for the weight attribute (default: 'weight') 75 | 8. `workers`: Number of workers for parallel execution (default: 1) 76 | 9. `sampling_strategy`: Node specific sampling strategies, supports setting node specific 'q', 'p', 'num_walks' and 'walk_length'. 77 | Use these keys exactly. If not set, will use the global ones which were passed on the object initialization` 78 | 10. `quiet`: Boolean controlling the verbosity. (default: False) 79 | 11. `temp_folder`: String path pointing to folder to save a shared memory copy of the graph - Supply when working on graphs that are too big to fit in memory during algorithm execution. 80 | 12. `seed`: Seed for the random number generator (default: None). Deterministic results can be obtained if seed is set and `workers=1`. 81 | 82 | - `Node2Vec.fit` method: 83 | Accepts any key word argument acceptable by gensim.Word2Vec 84 | 85 | #### `node2vec.EdgeEmbedder` 86 | 87 | `EdgeEmbedder` is an abstract class which all the concrete edge embeddings class inherit from. 88 | The classes are `AverageEmbedder`, `HadamardEmbedder`, `WeightedL1Embedder` and `WeightedL2Embedder` which their practical definition could be found in the [paper](https://arxiv.org/pdf/1607.00653.pdf) on table 1 89 | Notice that edge embeddings are defined for any pair of nodes, connected or not and even node with itself. 90 | 91 | - Constructor: 92 | 1. `keyed_vectors`: A gensim.models.KeyedVectors instance containing the node embeddings 93 | 2. `quiet`: Boolean controlling the verbosity. (default: False) 94 | 95 | - `EdgeEmbedder.__getitem__(item)` method, better known as `EdgeEmbedder[item]`: 96 | 1. `item` - A tuple consisting of 2 nodes from the `keyed_vectors` passed in the constructor. Will return the embedding of the edge. 97 | 98 | - `EdgeEmbedder.as_keyed_vectors` method: Returns a `gensim.models.KeyedVectors` instance with all possible node pairs in a *sorted* manner as string. 99 | For example, for nodes ['1', '2', '3'] we will have as keys "('1', '1')", "('1', '2')", "('1', '3')", "('2', '2')", "('2', '3')" and "('3', '3')". 100 | 101 | ## Caveats 102 | - Node names in the input graph must be all strings, or all ints 103 | - Parallel execution not working on Windows (`joblib` known issue). To run non-parallel on Windows pass `workers=1` on the `Node2Vec`'s constructor 104 | 105 | ## TODO 106 | - [x] Parallel implementation for walk generation 107 | - [ ] Parallel implementation for probability precomputation 108 | -------------------------------------------------------------------------------- /example.py: -------------------------------------------------------------------------------- 1 | import networkx as nx 2 | from node2vec import Node2Vec 3 | 4 | # FILES 5 | EMBEDDING_FILENAME = './embeddings.emb' 6 | EMBEDDING_MODEL_FILENAME = './embeddings.model' 7 | 8 | # Create a graph 9 | graph = nx.fast_gnp_random_graph(n=100, p=0.5) 10 | 11 | # Precompute probabilities and generate walks 12 | node2vec = Node2Vec(graph, dimensions=64, walk_length=30, num_walks=200, workers=4) 13 | 14 | ## if d_graph is big enough to fit in the memory, pass temp_folder which has enough disk space 15 | # Note: It will trigger "sharedmem" in Parallel, which will be slow on smaller graphs 16 | #node2vec = Node2Vec(graph, dimensions=64, walk_length=30, num_walks=200, workers=4, temp_folder="/mnt/tmp_data") 17 | 18 | # Embed 19 | model = node2vec.fit(window=10, min_count=1, batch_words=4) # Any keywords acceptable by gensim.Word2Vec can be passed, `dimensions` and `workers` are automatically passed (from the Node2Vec constructor) 20 | 21 | # Look for most similar nodes 22 | model.wv.most_similar('2') # Output node names are always strings 23 | 24 | # Save embeddings for later use 25 | model.wv.save_word2vec_format(EMBEDDING_FILENAME) 26 | 27 | # Save model for later use 28 | model.save(EMBEDDING_MODEL_FILENAME) 29 | -------------------------------------------------------------------------------- /node2vec/__init__.py: -------------------------------------------------------------------------------- 1 | from . import edges 2 | from .node2vec import Node2Vec 3 | from importlib import metadata 4 | 5 | __version__ = metadata.version('node2vec') 6 | -------------------------------------------------------------------------------- /node2vec/check_gensim.py: -------------------------------------------------------------------------------- 1 | from importlib.metadata import version 2 | 3 | def is_dated_gensim_version(): 4 | return version("gensim") < '4.0.0' -------------------------------------------------------------------------------- /node2vec/edges.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | from functools import reduce 3 | from itertools import combinations_with_replacement 4 | 5 | import numpy as np 6 | from .check_gensim import is_dated_gensim_version 7 | from gensim.models import KeyedVectors 8 | from tqdm import tqdm 9 | 10 | class EdgeEmbedder(ABC): 11 | INDEX_MAPPING_KEY = 'index2word' if is_dated_gensim_version() else 'index_to_key' 12 | 13 | def __init__(self, keyed_vectors: KeyedVectors, quiet: bool = False): 14 | """ 15 | :param keyed_vectors: KeyedVectors containing nodes and embeddings to calculate edges for 16 | """ 17 | 18 | self.kv = keyed_vectors 19 | self.quiet = quiet 20 | 21 | @abstractmethod 22 | def _embed(self, edge: tuple) -> np.ndarray: 23 | """ 24 | Abstract method for implementing the embedding method 25 | :param edge: tuple of two nodes 26 | :return: Edge embedding 27 | """ 28 | pass 29 | 30 | def __getitem__(self, edge) -> np.ndarray: 31 | if not isinstance(edge, tuple) or not len(edge) == 2: 32 | raise ValueError('edge must be a tuple of two nodes') 33 | 34 | if edge[0] not in getattr(self.kv, self.INDEX_MAPPING_KEY): 35 | raise KeyError('node {} does not exist in given KeyedVectors'.format(edge[0])) 36 | 37 | if edge[1] not in getattr(self.kv, self.INDEX_MAPPING_KEY): 38 | raise KeyError('node {} does not exist in given KeyedVectors'.format(edge[1])) 39 | 40 | return self._embed(edge) 41 | 42 | def as_keyed_vectors(self) -> KeyedVectors: 43 | """ 44 | Generated a KeyedVectors instance with all the possible edge embeddings 45 | :return: Edge embeddings 46 | """ 47 | 48 | edge_generator = combinations_with_replacement(getattr(self.kv, self.INDEX_MAPPING_KEY), r=2) 49 | 50 | if not self.quiet: 51 | vocab_size = len(getattr(self.kv, self.INDEX_MAPPING_KEY)) 52 | total_size = reduce(lambda x, y: x * y, range(1, vocab_size + 2)) / \ 53 | (2 * reduce(lambda x, y: x * y, range(1, vocab_size))) 54 | 55 | edge_generator = tqdm(edge_generator, desc='Generating edge features', total=total_size) 56 | 57 | # Generate features 58 | tokens = [] 59 | features = [] 60 | for edge in edge_generator: 61 | token = str(tuple(sorted(edge))) 62 | embedding = self._embed(edge) 63 | 64 | tokens.append(token) 65 | features.append(embedding) 66 | 67 | # Build KV instance 68 | edge_kv = KeyedVectors(vector_size=self.kv.vector_size) 69 | if is_dated_gensim_version(): 70 | edge_kv.add( 71 | entities=tokens, 72 | weights=features) 73 | else: 74 | edge_kv.add_vectors( 75 | keys=tokens, 76 | weights=features) 77 | 78 | return edge_kv 79 | 80 | 81 | class AverageEmbedder(EdgeEmbedder): 82 | """ 83 | Average node features 84 | """ 85 | 86 | def _embed(self, edge: tuple): 87 | return (self.kv[edge[0]] + self.kv[edge[1]]) / 2 88 | 89 | 90 | class HadamardEmbedder(EdgeEmbedder): 91 | """ 92 | Hadamard product node features 93 | """ 94 | 95 | def _embed(self, edge: tuple): 96 | return self.kv[edge[0]] * self.kv[edge[1]] 97 | 98 | 99 | class WeightedL1Embedder(EdgeEmbedder): 100 | """ 101 | Weighted L1 node features 102 | """ 103 | 104 | def _embed(self, edge: tuple): 105 | return np.abs(self.kv[edge[0]] - self.kv[edge[1]]) 106 | 107 | 108 | class WeightedL2Embedder(EdgeEmbedder): 109 | """ 110 | Weighted L2 node features 111 | """ 112 | 113 | def _embed(self, edge: tuple): 114 | return (self.kv[edge[0]] - self.kv[edge[1]]) ** 2 115 | -------------------------------------------------------------------------------- /node2vec/node2vec.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | from collections import defaultdict 4 | 5 | import gensim 6 | import networkx as nx 7 | import numpy as np 8 | from .check_gensim import is_dated_gensim_version 9 | from joblib import Parallel, delayed 10 | from tqdm.auto import tqdm 11 | 12 | from .parallel import parallel_generate_walks 13 | 14 | 15 | class Node2Vec: 16 | FIRST_TRAVEL_KEY = 'first_travel_key' 17 | PROBABILITIES_KEY = 'probabilities' 18 | NEIGHBORS_KEY = 'neighbors' 19 | WEIGHT_KEY = 'weight' 20 | NUM_WALKS_KEY = 'num_walks' 21 | WALK_LENGTH_KEY = 'walk_length' 22 | P_KEY = 'p' 23 | Q_KEY = 'q' 24 | 25 | def __init__(self, graph: nx.Graph, dimensions: int = 128, walk_length: int = 80, num_walks: int = 10, p: float = 1, 26 | q: float = 1, weight_key: str = 'weight', workers: int = 1, sampling_strategy: dict = None, 27 | quiet: bool = False, temp_folder: str = None, seed: int = None): 28 | """ 29 | Initiates the Node2Vec object, precomputes walking probabilities and generates the walks. 30 | 31 | :param graph: Input graph 32 | :param dimensions: Embedding dimensions (default: 128) 33 | :param walk_length: Number of nodes in each walk (default: 80) 34 | :param num_walks: Number of walks per node (default: 10) 35 | :param p: Return hyper parameter (default: 1) 36 | :param q: Inout parameter (default: 1) 37 | :param weight_key: On weighted graphs, this is the key for the weight attribute (default: 'weight') 38 | :param workers: Number of workers for parallel execution (default: 1) 39 | :param sampling_strategy: Node specific sampling strategies, supports setting node specific 'q', 'p', 'num_walks' and 'walk_length'. 40 | :param seed: Seed for the random number generator. 41 | Use these keys exactly. If not set, will use the global ones which were passed on the object initialization 42 | :param temp_folder: Path to folder with enough space to hold the memory map of self.d_graph (for big graphs); to be passed joblib.Parallel.temp_folder 43 | """ 44 | 45 | self.graph = graph 46 | self.dimensions = dimensions 47 | self.walk_length = walk_length 48 | self.num_walks = num_walks 49 | self.p = p 50 | self.q = q 51 | self.weight_key = weight_key 52 | self.workers = workers 53 | self.quiet = quiet 54 | self.d_graph = defaultdict(dict) 55 | 56 | if sampling_strategy is None: 57 | self.sampling_strategy = {} 58 | else: 59 | self.sampling_strategy = sampling_strategy 60 | 61 | self.temp_folder, self.require = None, None 62 | if temp_folder: 63 | if not os.path.isdir(temp_folder): 64 | raise NotADirectoryError("temp_folder does not exist or is not a directory. ({})".format(temp_folder)) 65 | 66 | self.temp_folder = temp_folder 67 | self.require = "sharedmem" 68 | 69 | if seed is not None: 70 | random.seed(seed) 71 | np.random.seed(seed) 72 | 73 | self._precompute_probabilities() 74 | self.walks = self._generate_walks() 75 | 76 | def _precompute_probabilities(self): 77 | """ 78 | Precomputes transition probabilities for each node. 79 | """ 80 | 81 | d_graph = self.d_graph 82 | 83 | nodes_generator = self.graph.nodes() if self.quiet \ 84 | else tqdm(self.graph.nodes(), desc='Computing transition probabilities') 85 | 86 | for source in nodes_generator: 87 | 88 | # Init probabilities dict for first travel 89 | if self.PROBABILITIES_KEY not in d_graph[source]: 90 | d_graph[source][self.PROBABILITIES_KEY] = dict() 91 | 92 | for current_node in self.graph.neighbors(source): 93 | 94 | # Init probabilities dict 95 | if self.PROBABILITIES_KEY not in d_graph[current_node]: 96 | d_graph[current_node][self.PROBABILITIES_KEY] = dict() 97 | 98 | unnormalized_weights = list() 99 | d_neighbors = list() 100 | 101 | # Calculate unnormalized weights 102 | for destination in self.graph.neighbors(current_node): 103 | 104 | p = self.sampling_strategy[current_node].get(self.P_KEY, 105 | self.p) if current_node in self.sampling_strategy else self.p 106 | q = self.sampling_strategy[current_node].get(self.Q_KEY, 107 | self.q) if current_node in self.sampling_strategy else self.q 108 | 109 | try: 110 | if self.graph[current_node][destination].get(self.weight_key): 111 | weight = self.graph[current_node][destination].get(self.weight_key, 1) 112 | else: 113 | ## Example : AtlasView({0: {'type': 1, 'weight':0.1}})- when we have edge weight 114 | edge = list(self.graph[current_node][destination])[-1] 115 | weight = self.graph[current_node][destination][edge].get(self.weight_key, 1) 116 | 117 | except: 118 | weight = 1 119 | 120 | if destination == source: # Backwards probability 121 | ss_weight = weight * 1 / p 122 | elif destination in self.graph[source]: # If the neighbor is connected to the source 123 | ss_weight = weight 124 | else: 125 | ss_weight = weight * 1 / q 126 | 127 | # Assign the unnormalized sampling strategy weight, normalize during random walk 128 | unnormalized_weights.append(ss_weight) 129 | d_neighbors.append(destination) 130 | 131 | # Normalize 132 | unnormalized_weights = np.array(unnormalized_weights) 133 | d_graph[current_node][self.PROBABILITIES_KEY][ 134 | source] = unnormalized_weights / unnormalized_weights.sum() 135 | 136 | # Calculate first_travel weights for source 137 | first_travel_weights = [] 138 | 139 | for destination in self.graph.neighbors(source): 140 | first_travel_weights.append(self.graph[source][destination].get(self.weight_key, 1)) 141 | 142 | first_travel_weights = np.array(first_travel_weights) 143 | d_graph[source][self.FIRST_TRAVEL_KEY] = first_travel_weights / first_travel_weights.sum() 144 | 145 | # Save neighbors 146 | d_graph[source][self.NEIGHBORS_KEY] = list(self.graph.neighbors(source)) 147 | 148 | def _generate_walks(self) -> list: 149 | """ 150 | Generates the random walks which will be used as the skip-gram input. 151 | :return: List of walks. Each walk is a list of nodes. 152 | """ 153 | 154 | flatten = lambda l: [item for sublist in l for item in sublist] 155 | 156 | # Split num_walks for each worker 157 | num_walks_lists = np.array_split(range(self.num_walks), self.workers) 158 | 159 | walk_results = Parallel(n_jobs=self.workers, temp_folder=self.temp_folder, require=self.require)( 160 | delayed(parallel_generate_walks)(self.d_graph, 161 | self.walk_length, 162 | len(num_walks), 163 | idx, 164 | self.sampling_strategy, 165 | self.NUM_WALKS_KEY, 166 | self.WALK_LENGTH_KEY, 167 | self.NEIGHBORS_KEY, 168 | self.PROBABILITIES_KEY, 169 | self.FIRST_TRAVEL_KEY, 170 | self.quiet) for 171 | idx, num_walks 172 | in enumerate(num_walks_lists, 1)) 173 | 174 | walks = flatten(walk_results) 175 | 176 | return walks 177 | 178 | def fit(self, **skip_gram_params) -> gensim.models.Word2Vec: 179 | """ 180 | Creates the embeddings using gensim's Word2Vec. 181 | :param skip_gram_params: Parameters for gensim.models.Word2Vec - do not supply 'size' / 'vector_size' it is 182 | taken from the Node2Vec 'dimensions' parameter 183 | :type skip_gram_params: dict 184 | :return: A gensim word2vec model 185 | """ 186 | 187 | if 'workers' not in skip_gram_params: 188 | skip_gram_params['workers'] = self.workers 189 | 190 | # Figure out gensim version, naming of output dimensions changed from size to vector_size in v4.0.0 191 | size = 'size' if is_dated_gensim_version() else 'vector_size' 192 | if size not in skip_gram_params: 193 | skip_gram_params[size] = self.dimensions 194 | 195 | if 'sg' not in skip_gram_params: 196 | skip_gram_params['sg'] = 1 197 | 198 | return gensim.models.Word2Vec(self.walks, **skip_gram_params) 199 | -------------------------------------------------------------------------------- /node2vec/parallel.py: -------------------------------------------------------------------------------- 1 | import random 2 | from tqdm import tqdm 3 | 4 | 5 | def parallel_generate_walks(d_graph: dict, global_walk_length: int, num_walks: int, cpu_num: int, 6 | sampling_strategy: dict = None, num_walks_key: str = None, walk_length_key: str = None, 7 | neighbors_key: str = None, probabilities_key: str = None, first_travel_key: str = None, 8 | quiet: bool = False) -> list: 9 | """ 10 | Generates the random walks which will be used as the skip-gram input. 11 | 12 | :return: List of walks. Each walk is a list of nodes. 13 | """ 14 | 15 | walks = list() 16 | 17 | if not quiet: 18 | pbar = tqdm(total=num_walks, desc='Generating walks (CPU: {})'.format(cpu_num)) 19 | 20 | for n_walk in range(num_walks): 21 | 22 | # Update progress bar 23 | if not quiet: 24 | pbar.update(1) 25 | 26 | # Shuffle the nodes 27 | shuffled_nodes = list(d_graph.keys()) 28 | random.shuffle(shuffled_nodes) 29 | 30 | # Start a random walk from every node 31 | for source in shuffled_nodes: 32 | 33 | # Skip nodes with specific num_walks 34 | if source in sampling_strategy and \ 35 | num_walks_key in sampling_strategy[source] and \ 36 | sampling_strategy[source][num_walks_key] <= n_walk: 37 | continue 38 | 39 | # Start walk 40 | walk = [source] 41 | 42 | # Calculate walk length 43 | if source in sampling_strategy: 44 | walk_length = sampling_strategy[source].get(walk_length_key, global_walk_length) 45 | else: 46 | walk_length = global_walk_length 47 | 48 | # Perform walk 49 | while len(walk) < walk_length: 50 | 51 | walk_options = d_graph[walk[-1]].get(neighbors_key, None) 52 | 53 | # Skip dead end nodes 54 | if not walk_options: 55 | break 56 | 57 | if len(walk) == 1: # For the first step 58 | probabilities = d_graph[walk[-1]][first_travel_key] 59 | walk_to = random.choices(walk_options, weights=probabilities)[0] 60 | else: 61 | probabilities = d_graph[walk[-1]][probabilities_key][walk[-2]] 62 | walk_to = random.choices(walk_options, weights=probabilities)[0] 63 | 64 | walk.append(walk_to) 65 | 66 | walk = list(map(str, walk)) # Convert all to strings 67 | 68 | walks.append(walk) 69 | 70 | if not quiet: 71 | pbar.close() 72 | 73 | return walks 74 | -------------------------------------------------------------------------------- /node2vec/setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "colorama" 5 | version = "0.4.6" 6 | description = "Cross-platform colored terminal text." 7 | optional = false 8 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 9 | files = [ 10 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 11 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 12 | ] 13 | 14 | [[package]] 15 | name = "gensim" 16 | version = "4.3.3" 17 | description = "Python framework for fast Vector Space Modelling" 18 | optional = false 19 | python-versions = ">=3.8" 20 | files = [ 21 | {file = "gensim-4.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4e72840adfbea35c5804fd559bc0cb6bc9f439926220a37d852b7ce76eb325c1"}, 22 | {file = "gensim-4.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4019263c9d9afae7c669f880c17e09461e77a71afce04ed4d79cf71a4cad2848"}, 23 | {file = "gensim-4.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dea62d3e2ada547687bde6cbba37efa50b534db77e9d44fd5802676bb072c9d9"}, 24 | {file = "gensim-4.3.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fac93ef5e44982defef9d3c1e4cd00245506b8a29cec19ec5e00f0221b8144c"}, 25 | {file = "gensim-4.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:7c3409f755fb8d62da99cea65e7a40a99d21f8fd86443a3aaf2d90eb68995021"}, 26 | {file = "gensim-4.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:99e7b70352aecc6c1674dde82b75f453e7a5d1cc71ac1cfbc460bf1fe20501b7"}, 27 | {file = "gensim-4.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:32a4cac3f3c38af2069eab9524609fc92ebaeb2692b7280cfda365a3517a280a"}, 28 | {file = "gensim-4.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c071b4329ed1be02446eb7ef637b94c68cf0080c15c57fbcde667fce2e49c3fe"}, 29 | {file = "gensim-4.3.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d662bf96e3d741b6ab61a54be842a7cbf5e45193008b2f4225c758cafd7f9cdc"}, 30 | {file = "gensim-4.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a54bd53a0e6f991abb837f126663353657270e75be53287e8a568ada0b35b1b0"}, 31 | {file = "gensim-4.3.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9a65ed1a8c1fc83890b4eb2a45ae2b32e82a0209c970c8c74694d0374c2415cb"}, 32 | {file = "gensim-4.3.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4db485e08a0287e0fd6a029d89b90913d1df38f1dcd34cd2ab758873ba9255f3"}, 33 | {file = "gensim-4.3.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7198987116373ab99f034b292a04ac841531d12b56345851c98b40a3fcd93a85"}, 34 | {file = "gensim-4.3.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6237a50de4da7a037b19b2b6c430b6537243dcdedebf94afeb089e951953e601"}, 35 | {file = "gensim-4.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:c910c2d5a71f532273166a3a82762959973f0513b221a495fa5a2a07652ee66d"}, 36 | {file = "gensim-4.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d7efa5e35d3f0ec02e6e8343b623c2c863be99e8c26866cf0bebd24fb10198c"}, 37 | {file = "gensim-4.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2e8eaf5ef576f4d45e98cf87e7edda9afb469dff954a923402dc1ffc35195901"}, 38 | {file = "gensim-4.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9161e52a6ec2a0580df66e9fac4ff7fc43efdc40674fbd4dd9e914796cc68bc3"}, 39 | {file = "gensim-4.3.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a200d6ac522cdf91e6048e1a368318c6b1b6e0c79009dfd408345ea2b9d3c096"}, 40 | {file = "gensim-4.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:065547124a93948926b88cb854e1c09750e9a4c7be92f55858159aa8a23359c3"}, 41 | {file = "gensim-4.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688a13b9bba839fedc7f3da6806d5701a756ed940839702ba6d7f494e917baef"}, 42 | {file = "gensim-4.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c560d28133cca58078221d60fce346f98f2c5e93d2ad42942f32c0d60903f65b"}, 43 | {file = "gensim-4.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:832311f0c420c0841c98b9e6cc4d83ea362add6db917bf2d646de4bed48a29f7"}, 44 | {file = "gensim-4.3.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1049f5bc2a84b21a1cb9976741826c0ebf25cfdff4a888361db4b4a697d99f0d"}, 45 | {file = "gensim-4.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:e99b236b6638a30d7f878e2e21a94dab2f6d4b4fd3c242f44dca1341940cb0cb"}, 46 | {file = "gensim-4.3.3.tar.gz", hash = "sha256:84852076a6a3d88d7dac5be245e24c21c3b819b565e14c1b61fa3e5ee76dcf57"}, 47 | ] 48 | 49 | [package.dependencies] 50 | numpy = ">=1.18.5,<2.0" 51 | scipy = ">=1.7.0,<1.14.0" 52 | smart-open = ">=1.8.1" 53 | 54 | [package.extras] 55 | distributed = ["Pyro4 (>=4.27)"] 56 | docs = ["POT", "Pyro4", "Pyro4 (>=4.27)", "annoy", "matplotlib", "memory-profiler", "nltk", "pandas", "pytest", "pytest-cov", "scikit-learn", "sphinx (==5.1.1)", "sphinx-gallery (==0.11.1)", "sphinxcontrib-napoleon (==0.7)", "sphinxcontrib.programoutput (==0.17)", "statsmodels", "testfixtures", "visdom (>=0.1.8,!=0.1.8.7)"] 57 | test = ["POT", "pytest", "pytest-cov", "testfixtures", "visdom (>=0.1.8,!=0.1.8.7)"] 58 | test-win = ["POT", "pytest", "pytest-cov", "testfixtures"] 59 | 60 | [[package]] 61 | name = "joblib" 62 | version = "1.4.2" 63 | description = "Lightweight pipelining with Python functions" 64 | optional = false 65 | python-versions = ">=3.8" 66 | files = [ 67 | {file = "joblib-1.4.2-py3-none-any.whl", hash = "sha256:06d478d5674cbc267e7496a410ee875abd68e4340feff4490bcb7afb88060ae6"}, 68 | {file = "joblib-1.4.2.tar.gz", hash = "sha256:2382c5816b2636fbd20a09e0f4e9dad4736765fdfb7dca582943b9c1366b3f0e"}, 69 | ] 70 | 71 | [[package]] 72 | name = "networkx" 73 | version = "3.1" 74 | description = "Python package for creating and manipulating graphs and networks" 75 | optional = false 76 | python-versions = ">=3.8" 77 | files = [ 78 | {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"}, 79 | {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"}, 80 | ] 81 | 82 | [package.extras] 83 | default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"] 84 | developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"] 85 | doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"] 86 | extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"] 87 | test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] 88 | 89 | [[package]] 90 | name = "numpy" 91 | version = "1.24.4" 92 | description = "Fundamental package for array computing in Python" 93 | optional = false 94 | python-versions = ">=3.8" 95 | files = [ 96 | {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, 97 | {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, 98 | {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, 99 | {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, 100 | {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, 101 | {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, 102 | {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, 103 | {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, 104 | {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, 105 | {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, 106 | {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, 107 | {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, 108 | {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, 109 | {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, 110 | {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, 111 | {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, 112 | {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, 113 | {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, 114 | {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, 115 | {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, 116 | {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, 117 | {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, 118 | {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, 119 | {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, 120 | {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, 121 | {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, 122 | {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, 123 | {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, 124 | ] 125 | 126 | [[package]] 127 | name = "scipy" 128 | version = "1.9.3" 129 | description = "Fundamental algorithms for scientific computing in Python" 130 | optional = false 131 | python-versions = ">=3.8" 132 | files = [ 133 | {file = "scipy-1.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1884b66a54887e21addf9c16fb588720a8309a57b2e258ae1c7986d4444d3bc0"}, 134 | {file = "scipy-1.9.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:83b89e9586c62e787f5012e8475fbb12185bafb996a03257e9675cd73d3736dd"}, 135 | {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a72d885fa44247f92743fc20732ae55564ff2a519e8302fb7e18717c5355a8b"}, 136 | {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01e1dd7b15bd2449c8bfc6b7cc67d630700ed655654f0dfcf121600bad205c9"}, 137 | {file = "scipy-1.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:68239b6aa6f9c593da8be1509a05cb7f9efe98b80f43a5861cd24c7557e98523"}, 138 | {file = "scipy-1.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b41bc822679ad1c9a5f023bc93f6d0543129ca0f37c1ce294dd9d386f0a21096"}, 139 | {file = "scipy-1.9.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:90453d2b93ea82a9f434e4e1cba043e779ff67b92f7a0e85d05d286a3625df3c"}, 140 | {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c06e62a390a9167da60bedd4575a14c1f58ca9dfde59830fc42e5197283dab"}, 141 | {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abaf921531b5aeaafced90157db505e10345e45038c39e5d9b6c7922d68085cb"}, 142 | {file = "scipy-1.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:06d2e1b4c491dc7d8eacea139a1b0b295f74e1a1a0f704c375028f8320d16e31"}, 143 | {file = "scipy-1.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a04cd7d0d3eff6ea4719371cbc44df31411862b9646db617c99718ff68d4840"}, 144 | {file = "scipy-1.9.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:545c83ffb518094d8c9d83cce216c0c32f8c04aaf28b92cc8283eda0685162d5"}, 145 | {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d54222d7a3ba6022fdf5773931b5d7c56efe41ede7f7128c7b1637700409108"}, 146 | {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cff3a5295234037e39500d35316a4c5794739433528310e117b8a9a0c76d20fc"}, 147 | {file = "scipy-1.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:2318bef588acc7a574f5bfdff9c172d0b1bf2c8143d9582e05f878e580a3781e"}, 148 | {file = "scipy-1.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d644a64e174c16cb4b2e41dfea6af722053e83d066da7343f333a54dae9bc31c"}, 149 | {file = "scipy-1.9.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:da8245491d73ed0a994ed9c2e380fd058ce2fa8a18da204681f2fe1f57f98f95"}, 150 | {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db5b30849606a95dcf519763dd3ab6fe9bd91df49eba517359e450a7d80ce2e"}, 151 | {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c68db6b290cbd4049012990d7fe71a2abd9ffbe82c0056ebe0f01df8be5436b0"}, 152 | {file = "scipy-1.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:5b88e6d91ad9d59478fafe92a7c757d00c59e3bdc3331be8ada76a4f8d683f58"}, 153 | {file = "scipy-1.9.3.tar.gz", hash = "sha256:fbc5c05c85c1a02be77b1ff591087c83bc44579c6d2bd9fb798bb64ea5e1a027"}, 154 | ] 155 | 156 | [package.dependencies] 157 | numpy = ">=1.18.5,<1.26.0" 158 | 159 | [package.extras] 160 | dev = ["flake8", "mypy", "pycodestyle", "typing_extensions"] 161 | doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-panels (>=0.5.2)", "sphinx-tabs"] 162 | test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] 163 | 164 | [[package]] 165 | name = "smart-open" 166 | version = "7.0.4" 167 | description = "Utils for streaming large files (S3, HDFS, GCS, Azure Blob Storage, gzip, bz2...)" 168 | optional = false 169 | python-versions = "<4.0,>=3.7" 170 | files = [ 171 | {file = "smart_open-7.0.4-py3-none-any.whl", hash = "sha256:4e98489932b3372595cddc075e6033194775165702887216b65eba760dfd8d47"}, 172 | {file = "smart_open-7.0.4.tar.gz", hash = "sha256:62b65852bdd1d1d516839fcb1f6bc50cd0f16e05b4ec44b52f43d38bcb838524"}, 173 | ] 174 | 175 | [package.dependencies] 176 | wrapt = "*" 177 | 178 | [package.extras] 179 | all = ["azure-common", "azure-core", "azure-storage-blob", "boto3", "google-cloud-storage (>=2.6.0)", "paramiko", "requests", "zstandard"] 180 | azure = ["azure-common", "azure-core", "azure-storage-blob"] 181 | gcs = ["google-cloud-storage (>=2.6.0)"] 182 | http = ["requests"] 183 | s3 = ["boto3"] 184 | ssh = ["paramiko"] 185 | test = ["azure-common", "azure-core", "azure-storage-blob", "boto3", "google-cloud-storage (>=2.6.0)", "moto[server]", "paramiko", "pytest", "pytest-rerunfailures", "requests", "responses", "zstandard"] 186 | webhdfs = ["requests"] 187 | zst = ["zstandard"] 188 | 189 | [[package]] 190 | name = "tqdm" 191 | version = "4.66.4" 192 | description = "Fast, Extensible Progress Meter" 193 | optional = false 194 | python-versions = ">=3.7" 195 | files = [ 196 | {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"}, 197 | {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"}, 198 | ] 199 | 200 | [package.dependencies] 201 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 202 | 203 | [package.extras] 204 | dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] 205 | notebook = ["ipywidgets (>=6)"] 206 | slack = ["slack-sdk"] 207 | telegram = ["requests"] 208 | 209 | [[package]] 210 | name = "wrapt" 211 | version = "1.16.0" 212 | description = "Module for decorators, wrappers and monkey patching." 213 | optional = false 214 | python-versions = ">=3.6" 215 | files = [ 216 | {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, 217 | {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, 218 | {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, 219 | {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, 220 | {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, 221 | {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, 222 | {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, 223 | {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, 224 | {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, 225 | {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, 226 | {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, 227 | {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, 228 | {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, 229 | {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, 230 | {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, 231 | {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, 232 | {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, 233 | {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, 234 | {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, 235 | {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, 236 | {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, 237 | {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, 238 | {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, 239 | {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, 240 | {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, 241 | {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, 242 | {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, 243 | {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, 244 | {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, 245 | {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, 246 | {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, 247 | {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, 248 | {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, 249 | {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, 250 | {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, 251 | {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, 252 | {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, 253 | {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, 254 | {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, 255 | {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, 256 | {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, 257 | {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, 258 | {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, 259 | {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, 260 | {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, 261 | {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, 262 | {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, 263 | {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, 264 | {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, 265 | {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, 266 | {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, 267 | {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, 268 | {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, 269 | {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, 270 | {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, 271 | {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, 272 | {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, 273 | {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, 274 | {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, 275 | {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, 276 | {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, 277 | {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, 278 | {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, 279 | {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, 280 | {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, 281 | {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, 282 | {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, 283 | {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, 284 | {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, 285 | {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, 286 | ] 287 | 288 | [metadata] 289 | lock-version = "2.0" 290 | python-versions = "^3.8" 291 | content-hash = "66b077ba276a9b44c8aa80ba21aa5805641622e5be27324e6c39f5d7b04c8d13" 292 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "node2vec" 3 | version = "0.5.0" 4 | description = "Implementation of the node2vec algorithm" 5 | authors = ["elior "] 6 | repository = "https://github.com/eliorc/node2vec" 7 | license = "MIT" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.8" 11 | networkx = "^3.1.0" 12 | gensim = "^4.3.0" 13 | numpy = "^1.24.0" 14 | tqdm = "^4.66.1" 15 | joblib = "^1.4.0" 16 | 17 | [tool.poetry.dev-dependencies] 18 | 19 | [build-system] 20 | requires = ["poetry-core>=1.0.0"] 21 | build-backend = "poetry.core.masonry.api" 22 | --------------------------------------------------------------------------------