Source code for qbiocode.apps.quvine.baselines.node2vec

# Copyright 2026, IBM Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import numpy as np
from qbiocode.apps.quvine._deps import require_module


def _node2vec_class():
    """Resolve node2vec.Node2Vec at call time, not import time.

    The node2vec distribution is provided by the [quvine] extra. Note that it
    imports the deprecated pkg_resources module, so the extra pins
    setuptools<81 -- without that pin this import fails even when node2vec
    itself is installed.

    Resolving it at *import* time would be wrong. ``baselines/__init__.py``
    imports this module inside ``try/except ImportError``, so a module-level
    failure left ``run_node2vec`` unbound; ``baselines/adapters.py`` then
    imported that name to build the method registry and every registry method
    -- netmf, appnp, graphgps -- died with a node2vec-specific ImportError
    instead of naming its own missing dependency.
    """
    return require_module("node2vec", method="node2vec").Node2Vec


[docs] def run_node2vec( graph, nodes, dimensions=64, walk_length=10, num_walks=10, p=1.0, q=0.5, window=5, min_count=1, workers=8, seed=None, ): """ Run Node2Vec and return embeddings aligned to `nodes`. Parameters ---------- graph : networkx.Graph nodes : List[node] Canonical node ordering (must match graph_data.nodes) """ Node2Vec = _node2vec_class() node2vec = Node2Vec( graph, dimensions=dimensions, walk_length=walk_length, num_walks=num_walks, p=p, q=q, workers=workers, seed=seed, ) model = node2vec.fit( window=window, min_count=min_count, batch_words=4, ) # --- align embeddings to nodes --- Z = np.zeros((len(nodes), dimensions), dtype=float) for i, node in enumerate(nodes): Z[i] = model.wv[node] return Z