Skip to main content

Crate pattern_core

Crate pattern_core 

Source
Expand description

pattern-core - Core pattern data structures

This crate provides the core pattern data structures for the pattern-rs library. It is a faithful port of the gram-hs reference implementation.

§Overview

The pattern-core crate defines these main types:

  • StandardGraph: An ergonomic, zero-configuration graph for building and querying graph structures. This is the recommended starting point for most users.

  • Subject: A self-descriptive value type with identity, labels, and properties. Use Subject::build for fluent construction.

  • Pattern<V>: A recursive, nested structure (s-expression-like) that is generic over value type V. This is the foundational data structure for representing nested, hierarchical data that may be interpreted as graphs.

§Quick Start

Build a graph with StandardGraph:

use pattern_core::graph::StandardGraph;
use pattern_core::subject::Subject;

let mut g = StandardGraph::new();

// Add nodes using the fluent SubjectBuilder
let alice = Subject::build("alice").label("Person").property("name", "Alice").done();
let bob   = Subject::build("bob").label("Person").property("name", "Bob").done();
g.add_node(alice.clone());
g.add_node(bob.clone());

// Add a relationship — pass the Subject objects directly
g.add_relationship(Subject::build("r1").label("KNOWS").done(), &alice, &bob);

assert_eq!(g.node_count(), 2);
assert_eq!(g.relationship_count(), 1);

// Query the graph
let source = g.source(&"r1".into()).unwrap();
assert_eq!(source.value.identity.0, "alice");
let neighbors = g.neighbors(&"bob".into());
assert_eq!(neighbors.len(), 1);

§Low-Level Pattern Construction

For direct pattern manipulation without the graph layer:

use pattern_core::{Pattern, Subject, Symbol, Value};
use std::collections::{HashSet, HashMap};

// Create an atomic pattern (special case)
let atomic = Pattern::point("hello".to_string());

// Create a pattern with elements (primary constructor)
let pattern = Pattern::pattern("parent".to_string(), vec![
    Pattern::point("child1".to_string()),
    Pattern::point("child2".to_string()),
]);

// Access pattern components
assert_eq!(atomic.value(), "hello");
assert_eq!(pattern.length(), 2);
assert_eq!(pattern.depth(), 1);

// Transform pattern values (Functor)
let upper = pattern.clone().map(|s| s.to_uppercase());
assert_eq!(upper.value(), "PARENT");

// Validate pattern structure
use pattern_core::ValidationRules;
let rules = ValidationRules {
    max_depth: Some(10),
    ..Default::default()
};
assert!(pattern.validate(&rules).is_ok());

// Analyze pattern structure
let analysis = pattern.analyze_structure();
println!("Structure: {}", analysis.summary);

// Create a pattern with Subject value
let subject = Subject {
    identity: Symbol("n".to_string()),
    labels: {
        let mut s = HashSet::new();
        s.insert("Person".to_string());
        s
    },
    properties: {
        let mut m = HashMap::new();
        m.insert("name".to_string(), Value::VString("Alice".to_string()));
        m
    },
};

let pattern_with_subject: Pattern<Subject> = Pattern::point(subject);

§Pattern Combination

Patterns can be combined associatively using the combine() method when the value type implements the Combinable trait. Combination merges two patterns by combining their values and concatenating their elements.

use pattern_core::{Pattern, Combinable};

// Combine atomic patterns (no elements)
let p1 = Pattern::point("hello".to_string());
let p2 = Pattern::point(" world".to_string());
let combined = p1.combine(p2);
assert_eq!(combined.value(), "hello world");
assert_eq!(combined.length(), 0);

// Combine patterns with elements
let p3 = Pattern::pattern("a".to_string(), vec![
    Pattern::point("b".to_string()),
    Pattern::point("c".to_string()),
]);
let p4 = Pattern::pattern("d".to_string(), vec![
    Pattern::point("e".to_string()),
]);
let result = p3.combine(p4);
assert_eq!(result.value(), "ad");
assert_eq!(result.length(), 3); // [b, c, e]

// Associativity: (a ⊕ b) ⊕ c = a ⊕ (b ⊕ c)
let a = Pattern::point("a".to_string());
let b = Pattern::point("b".to_string());
let c = Pattern::point("c".to_string());
let left = a.clone().combine(b.clone()).combine(c.clone());
let right = a.combine(b.combine(c));
assert_eq!(left, right);

§Pattern Ordering

Patterns implement Ord and PartialOrd for types that support ordering, enabling sorting, comparison, and use in ordered data structures.

use pattern_core::Pattern;
use std::collections::{BTreeSet, BTreeMap};

// Compare patterns
let p1 = Pattern::point(1);
let p2 = Pattern::point(2);
assert!(p1 < p2);

// Value-first ordering: values compared before elements
let p3 = Pattern::pattern(3, vec![Pattern::point(100)]);
let p4 = Pattern::pattern(4, vec![Pattern::point(1)]);
assert!(p3 < p4); // 3 < 4, elements not compared

// Sort patterns
let mut patterns = vec![
    Pattern::point(5),
    Pattern::point(2),
    Pattern::point(8),
];
patterns.sort();
assert_eq!(patterns[0], Pattern::point(2));

// Find min/max
let min = patterns.iter().min().unwrap();
let max = patterns.iter().max().unwrap();
assert_eq!(min, &Pattern::point(2));
assert_eq!(max, &Pattern::point(8));

// Use in BTreeSet (maintains sorted order)
let mut set = BTreeSet::new();
set.insert(Pattern::point(5));
set.insert(Pattern::point(2));
set.insert(Pattern::point(8));
let sorted: Vec<_> = set.iter().map(|p| p.value).collect();
assert_eq!(sorted, vec![2, 5, 8]);

// Use as BTreeMap keys
let mut map = BTreeMap::new();
map.insert(Pattern::point(1), "first");
map.insert(Pattern::point(2), "second");
assert_eq!(map.get(&Pattern::point(1)), Some(&"first"));

§WASM Compatibility

All types in this crate are fully compatible with WebAssembly targets. Compile for WASM with:

cargo build --package pattern-core --target wasm32-unknown-unknown

§Reference Implementation

This crate is ported from the gram-hs reference implementation:

  • Pattern: ../pattern-hs/libs/pattern/src/Pattern.hs
  • Subject: ../pattern-hs/libs/subject/src/Subject/Core.hs
  • Feature Spec: ../pattern-hs/specs/001-pattern-data-structure/

Re-exports§

pub use graph::all_paths;
pub use graph::betweenness_centrality;
pub use graph::bfs;
pub use graph::canonical_classifier;
pub use graph::classify_by_shape;
pub use graph::connected_components;
pub use graph::degree_centrality;
pub use graph::dfs;
pub use graph::directed;
pub use graph::directed_reverse;
pub use graph::filter_graph;
pub use graph::fold_graph;
pub use graph::frame_query;
pub use graph::from_graph_lens;
pub use graph::from_pattern_graph;
pub use graph::from_test_node;
pub use graph::has_cycle;
pub use graph::has_path;
pub use graph::is_connected;
pub use graph::is_neighbor;
pub use graph::map_all_graph;
pub use graph::map_graph;
pub use graph::map_with_context;
pub use graph::materialize;
pub use graph::memoize_incident_rels;
pub use graph::minimum_spanning_tree;
pub use graph::para_graph;
pub use graph::para_graph_fixed;
pub use graph::query_annotations_of;
pub use graph::query_co_members;
pub use graph::query_walks_containing;
pub use graph::shortest_path;
pub use graph::topological_sort;
pub use graph::undirected;
pub use graph::unfold_graph;
pub use graph::unfold_graph;
pub use graph::CategoryMappers;
pub use graph::GraphClass;
pub use graph::GraphClassifier;
pub use graph::GraphQuery;
pub use graph::GraphValue;
pub use graph::GraphView;
pub use graph::StandardGraph;
pub use graph::Substitution;
pub use graph::TraversalDirection;
pub use graph::TraversalWeight;
pub use pattern::unfold;
pub use pattern::unfold;
pub use pattern::Pattern;
pub use pattern::StructureAnalysis;
pub use pattern::ValidationError;
pub use pattern::ValidationRules;
pub use pattern_graph::from_pattern_graph as graph_query_from_pattern_graph;
pub use pattern_graph::from_patterns;
pub use pattern_graph::from_patterns_with_policy;
pub use pattern_graph::merge as pg_merge;
pub use pattern_graph::merge_with_policy as pg_merge_with_policy;
pub use pattern_graph::PatternGraph;
pub use reconcile::ElementMergeStrategy;
pub use reconcile::HasIdentity;
pub use reconcile::LabelMerge;
pub use reconcile::Mergeable;
pub use reconcile::PropertyMerge;
pub use reconcile::ReconciliationPolicy;
pub use reconcile::Refinable;
pub use reconcile::SubjectMergeStrategy;
pub use subject::PropertyRecord;
pub use subject::RangeValue;
pub use subject::Subject;
pub use subject::SubjectBuilder;
pub use subject::Symbol;
pub use subject::Value;

Modules§

graph
pattern
pattern_graph
PatternGraph: typed container for nodes, relationships, walks, and annotations.
reconcile
Pattern reconciliation for normalizing duplicate identities.
subject
Subject type definition
test_utils
Test utilities for pattern testing infrastructure

Structs§

EmptySubject
Newtype wrapper for “empty” combination strategy that creates anonymous subjects.
FirstSubject
Newtype wrapper for “first wins” combination strategy.
LastSubject
Newtype wrapper for “last wins” combination strategy.

Traits§

Combinable
Types that support associative combination.