Skip to main content

find_subgraph_patterns

Function find_subgraph_patterns 

Source
pub fn find_subgraph_patterns(
    graph: &SqliteGraph,
    pattern: &SqliteGraph,
    bounds: SubgraphPatternBounds,
) -> Result<SubgraphMatchResult, SqliteGraphError>
Expand description

Finds all subgraph isomorphisms of pattern within graph.

Uses VF2 algorithm to find all occurrences of the pattern graph as a subgraph of the target graph. Returns all mappings from pattern nodes to target nodes.

§Arguments

  • graph - The target graph to search within
  • pattern - The pattern graph to search for
  • bounds - Limits on the search (max_matches, timeout, max_pattern_nodes)

§Returns

SubgraphMatchResult containing:

  • List of matches (each is a mapping from pattern index to target node ID)
  • Number of patterns found
  • Computation time in milliseconds
  • Whether search stopped due to bounds

§Example

use sqlitegraph::{algo::find_subgraph_patterns, SqliteGraph, GraphEntity};

// Create target graph: 0 -> 1 -> 2 -> 3
let graph = SqliteGraph::open_in_memory()?;
for i in 0..4 {
    let entity = GraphEntity {
        id: 0,
        kind: "node".to_string(),
        name: format!("n{}", i),
        file_path: None,
        data: serde_json::json!({}),
    };
    graph.insert_entity(&entity)?;
}

let ids: Vec<i64> = graph.all_entity_ids()?;
// Add edges for chain
for i in 0..3 {
    graph.insert_edge(&(ids[i], ids[i+1], "edge".to_string()))?;
}

// Create pattern: A -> B (2-node chain)
let pattern = SqliteGraph::open_in_memory()?;
for i in 0..2 {
    let entity = GraphEntity {
        id: 0,
        kind: "pattern".to_string(),
        name: format!("p{}", i),
        file_path: None,
        data: serde_json::json!({}),
    };
    pattern.insert_entity(&entity)?;
}

let pattern_ids: Vec<i64> = pattern.all_entity_ids()?;
pattern.insert_edge(&(pattern_ids[0], pattern_ids[1], "edge".to_string()))?;

// Find all occurrences of 2-node chain in 4-node path
// Should find 3 matches: (0,1), (1,2), (2,3)
let result = find_subgraph_patterns(&graph, &pattern, SubgraphPatternBounds::default())?;
assert_eq!(result.patterns_found, 3);

§Complexity

Time: O(n! × n) worst case, where n = pattern nodes Space: O(n + m) for recursion stack and match state

§Bounds

Always use bounds for patterns > 5 nodes or dense graphs:

  • max_matches: Prevents enumerating millions of matches
  • timeout_ms: Prevents hanging on exponential searches
  • max_pattern_nodes: Rejects large patterns early