Source code for qbiocode.apps.quvine.walks.dtqw

# 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 networkx as nx 
import numpy as np
from qbiocode.apps.quvine._deps import require_module
from qbiocode.apps.quvine.utils.utilities import sample_walks_from_distribution


def _hiperwalk():
    """Resolve hiperwalk at call time, not import time.

    hiperwalk is provided by the [quvine] extra; require_module turns its absence
    into a message naming the extra and the install command rather than a bare
    ModuleNotFoundError. Resolving it at *import* time would be wrong: walks/base.py
    imports this module eagerly, so an RWR-only run -- which never touches a quantum
    walk -- would fail with a DTQW message pointing at the wrong dependency.
    """
    return require_module("hiperwalk", feature="discrete-time (coined) quantum walks (DTQW)")


[docs] def get_coined_hiperwalk_scores(G, root, view_nodes=None, steps: int=25, coin: str="grover"): """ Return node probabilities from Hiperwalk coined quantum walk (CQW) Args: G (_type_): _description_ root (_type_): _description_ view_nodes (_type_, optional): _description_. Defaults to None. steps (int, optional): _description_. Defaults to 25. coin (str, optional): _description_. Defaults to "grover". """ if view_nodes is not None: G = G.subgraph(view_nodes) if root not in G: raise ValueError("Root node not in graph or view") nodes = list(G.nodes()) node2i = {n:i for i,n in enumerate(nodes)} i2node = {i:n for n,i in node2i.items()} G_int = nx.relabel_nodes(G,node2i, copy=True) #build hiperwalk graph + dtqw hpw = _hiperwalk() hg = hpw.Graph(G_int) qw = hpw.Coined(graph=hg, coin=coin) root_i = node2i[root] neighbors = list(G_int.neighbors(root_i)) if len(neighbors) == 0: raise ValueError("Root node has no neighbors in the graph or view") state0 = qw.ket(root_i) final_state = qw.simulate(range=(steps, steps+1), state=state0) #convert to node probability probs = qw.probability_distribution(final_state) probs = np.asarray(probs)[0] # 9) Map back to original node labels scores = {i2node[i]: float(probs[i]) for i in range(len(probs))} return scores
[docs] def generate_DTQW_walks(G, root, view_nodes=None, num_walks: int = 10, walk_length: int = 6, steps: int=25, coin: str="grover", rng=None): assert isinstance(rng, np.random.Generator) scores = get_coined_hiperwalk_scores(G, root=root, view_nodes=view_nodes, steps=steps, coin=coin) walks = sample_walks_from_distribution(scores, num_walks=num_walks, walk_length=walk_length, rng=rng) return walks