qbiocode.apps.quvine.baselines.graphgps module#
QuVINE GraphGPS variants using PyTorch Geometric.
Purpose#
This module treats GraphGPS as a classical downstream graph learner. It does not claim GraphGPS is quantum. The scientific question is whether quantum-walk-calibrated or direct quantum-walk features add useful signal relative to raw and classical-diffusion features under the same GraphGPS model.
Supported feature variants#
raw rwr heat_fixed poly_fixed heat_qcal_ctqw poly_qcal_ctqw heat_qcal_dtqw poly_qcal_dtqw heat_qcal_rwr poly_qcal_rwr direct_ctqw direct_dtqw
Notes
This module uses PyG’s GPSConv.
For link prediction, pass train_graph_for_message_passing so GraphGPS does not see validation/test edges during message passing.
Direct CTQW/DTQW features are expected as precomputed arrays, e.g. from your SGNS pipeline. This module does not recompute DTQW/CTQW walks internally.
Summary#
Classes:
Hyperparameters for the GraphGPS encoder. |
|
Node-level GraphGPS encoder. |
|
Training config for unsupervised link reconstruction or node classification. |
Functions:
Align a direct feature matrix/mapping to graph_nodes order. |
|
Align feature matrix to nodelist. |
|
Random walk with restart / PPR-style feature diffusion. |
|
Build one GraphGPS input feature matrix and metadata. |
|
Build classical RWR/PPR target distributions matching CTQW target supports. |
|
Fit heat time t to target distributions by local distribution matching. |
|
Fit monomial Laplacian polynomial coefficients to target distributions. |
|
Generate embeddings using one feature variant followed by GraphGPS. |
|
Generate GraphGPS embedding using standardized method names. |
|
Convert a NetworkX graph to PyG edge_index with stable node ordering. |
|
Create base node features used by all feature variants. |
|
Set random seeds for reproducibility. |
|
Standardize columns with optional train-only statistics. |
|
Reference#
- class GraphGPSConfig(hidden_dim=64, output_dim=128, num_layers=2, heads=4, dropout=0.2, attn_dropout=0.2, local_gnn='gcn', attn_type='multihead', use_layer_norm=True, activation='relu', lap_pe_dim=0, standardize_features=True)[source]#
Bases:
objectHyperparameters for the GraphGPS encoder.
-
output_dim:
int= 128#
-
num_layers:
int= 2#
-
heads:
int= 4#
-
dropout:
float= 0.2#
-
attn_dropout:
float= 0.2#
-
local_gnn:
str= 'gcn'#
-
attn_type:
str= 'multihead'#
-
use_layer_norm:
bool= True#
-
activation:
str= 'relu'#
-
lap_pe_dim:
int= 0#
-
standardize_features:
bool= True#
-
output_dim:
- class TrainConfig(task='link_reconstruction', epochs=200, lr=0.005, weight_decay=0.0005, patience=30, edge_batch_size=8192, val_edge_fraction=0.1, device='cpu', random_state=42, verbose=False)[source]#
Bases:
objectTraining config for unsupervised link reconstruction or node classification.
-
task:
str= 'link_reconstruction'#
-
epochs:
int= 200#
-
lr:
float= 0.005#
-
weight_decay:
float= 0.0005#
-
patience:
int= 30#
-
edge_batch_size:
int= 8192#
-
val_edge_fraction:
float= 0.1#
-
device:
str= 'cpu'#
-
random_state:
int= 42#
-
verbose:
bool= False#
-
task:
- standardize_columns(X, train_mask=None, eps=1e-12)[source]#
Standardize columns with optional train-only statistics.
If train_mask is provided, only those rows are used to compute mean/std. This mirrors the leakage fix used in gat.py.
- Return type:
ndarray
- align_features(features, nodelist, feature_nodes=None)[source]#
Align feature matrix to nodelist.
- Return type:
ndarray
- graph_to_edge_index(G, nodelist=None, add_reverse_edges=True, add_self_loops=False, device=None)[source]#
Convert a NetworkX graph to PyG edge_index with stable node ordering.
- Return type:
Any
- make_base_features(G, nodelist=None, embedding_dim=128, features=None, feature_nodes=None, feature_mode='structural', train_mask=None, random_state=42)[source]#
Create base node features used by all feature variants.
- Return type:
ndarray
- feature_mode:
‘provided’: require features.
‘random’: row-normalized random features.
‘structural’: scalable local structural features padded/projected to embedding_dim.
- Degenerate graphs:
Any structural column that networkx cannot compute for this graph class (clustering and triangles on multigraphs, k-core with self-loops, pagerank that fails to converge) falls back to zeros – pagerank to the uniform distribution – and logs the reason at DEBUG. The feature matrix always has the documented width; it is never partially built.
- apply_rwr_filter(G, X, nodelist, alpha=0.15, steps=50, tol=1e-06)[source]#
Random walk with restart / PPR-style feature diffusion.
- Return type:
ndarray
- calibrate_heat_kernel(L, targets, node_to_idx, t_grid=None, loss='l2')[source]#
Fit heat time t to target distributions by local distribution matching.
- Return type:
Tuple[float,float]
- calibrate_polynomial_filter(L, targets, node_to_idx, K=4, ridge=1e-05)[source]#
Fit monomial Laplacian polynomial coefficients to target distributions.
Important fix: no column normalization is applied during fitting, so the fitted basis matches the deployed polynomial basis.
- Return type:
ndarray
- build_rwr_targets_from_templates(G, templates, nodelist=None, alpha=0.15, steps=50, tol=1e-10)[source]#
Build classical RWR/PPR target distributions matching CTQW target supports.
- Return type:
List[Dict]
- align_direct_features(Z, graph_nodes, feature_nodes=None)[source]#
Align a direct feature matrix/mapping to graph_nodes order.
- Return type:
ndarray
- build_graphgps_input_features(G, variant, nodelist=None, train_mask=None, base_features=None, base_feature_nodes=None, embedding_dim=128, feature_mode='structural', ctqw_targets=None, dtqw_targets=None, rwr_targets=None, direct_features=None, direct_feature_nodes=None, normalize_laplacian=True, heat_t=1.0, poly_K=4, poly_ridge=1e-05, rwr_alpha=0.15, rwr_steps=50, random_state=42)[source]#
Build one GraphGPS input feature matrix and metadata.
- Return type:
Tuple[ndarray,Dict]
- class PyGGraphGPS(input_dim, config)[source]#
Bases:
ModuleNode-level GraphGPS encoder.
- forward(x, edge_index, batch=None)[source]#
Define the computation performed at every call.
Should be overridden by all subclasses.
Note
Although the recipe for forward pass needs to be defined within this function, one should call the
Moduleinstance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.
- build_pyg_data(G, X, nodelist=None, gps_config=None, train_graph_for_message_passing=None, train_mask=None)[source]#
- Return type:
Any
- train_graphgps_link_reconstruction(model, data, G_for_edges, nodelist, train_config)[source]#
- Return type:
Dict
- train_graphgps_node_classifier(model, data, y, train_mask, val_mask, num_classes, train_config)[source]#
- Return type:
Tuple[Any,Dict]
- generate_graphgps_embedding(G, variant, nodelist=None, train_mask=None, base_features=None, base_feature_nodes=None, embedding_dim=128, feature_mode='structural', ctqw_targets=None, dtqw_targets=None, rwr_targets=None, direct_features=None, direct_feature_nodes=None, train_graph_for_message_passing=None, train_graph_for_edges=None, y=None, val_mask=None, num_classes=None, gps_config=None, train_config=None, normalize_laplacian=True, heat_t=1.0, poly_K=4, poly_ridge=1e-05, rwr_alpha=0.15, rwr_steps=50)[source]#
Generate embeddings using one feature variant followed by GraphGPS.
If train_config.task == ‘none’, GraphGPS is untrained and returns initial forward pass.
- Return type:
Tuple[ndarray,Dict]
- generate_multiple_graphgps_embeddings(G, variants, **kwargs)[source]#
- Return type:
Tuple[Dict[str,ndarray],Dict[str,Dict]]
- generate_graphgps_embedding_by_method_name(G, method_name, embedding_dim=128, nodelist=None, base_features=None, ctqw_targets=None, dtqw_targets=None, rwr_targets=None, direct_features=None, heat_t=1.0, poly_K=4, rwr_alpha=0.15, gps_config=None, train_config=None, **kwargs)[source]#
Generate GraphGPS embedding using standardized method names.
This function maps the 12 standardized GraphGPS method names to the existing variant system in generate_graphgps_embedding.
- Supported methods:
graphgps_baseline: Raw structural features
graphgps_heat: Heat kernel filter only
graphgps_poly: Polynomial filter only
graphgps_rwr: RWR walk only
graphgps_ctqw: CTQW walk only (direct features)
graphgps_dtqw: DTQW walk only (direct features)
graphgps_rwr_heat: RWR + heat filter
graphgps_rwr_poly: RWR + polynomial filter
graphgps_ctqw_heat: CTQW + heat filter (quantum calibrated)
graphgps_ctqw_poly: CTQW + polynomial filter (quantum calibrated)
graphgps_dtqw_heat: DTQW + heat filter (quantum calibrated)
graphgps_dtqw_poly: DTQW + polynomial filter (quantum calibrated)
- Parameters:
G (
Graph) – NetworkX graphmethod_name (
str) – Standardized method name (e.g., ‘graphgps_baseline’, ‘graphgps_ctqw_heat’)embedding_dim (
int) – Output embedding dimensionnodelist (
Optional[Sequence]) – Ordered list of nodesbase_features (
Optional[ndarray]) – Pre-computed base featuresctqw_targets (
Optional[List[Dict]]) – CTQW calibration targetsdtqw_targets (
Optional[List[Dict]]) – DTQW calibration targetsrwr_targets (
Optional[List[Dict]]) – RWR calibration targetsdirect_features (
Optional[Mapping[str,Union[ndarray,Mapping]]]) – Direct walk features (for direct_ctqw/dtqw variants)heat_t (
float) – Heat kernel time parameter (for fixed variants)poly_K (
int) – Polynomial degreerwr_alpha (
float) – RWR restart probabilitygps_config (
Optional[GraphGPSConfig]) – GraphGPS model configurationtrain_config (
Optional[TrainConfig]) – Training configuration**kwargs – Additional arguments
- Return type:
ndarray- Returns:
Node embeddings [N, embedding_dim]
Example
>>> G = nx.karate_club_graph() >>> emb = generate_graphgps_embedding_by_method_name(G, 'graphgps_baseline', embedding_dim=64) >>> print(emb.shape) # (34, 64)
- Raises:
ValueError – If method_name is not recognized