use oxirs_core::model::*;
use oxirs_core::query::algebra::{AlgebraTriplePattern, TermPattern as AlgebraTermPattern};
use oxirs_core::query::pattern_optimizer::IndexStats;
use oxirs_core::query::{PatternExecutor, PatternOptimizer};
use oxirs_core::store::IndexedGraph;
use std::sync::Arc;
use std::time::Instant;
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("=== Pattern Matching Optimization Example ===\n");
let graph = Arc::new(IndexedGraph::new());
let stats = Arc::new(IndexStats::new());
populate_sample_data(&graph)?;
println!("Example 1: Basic Pattern Optimization");
basic_pattern_optimization(&stats)?;
println!("\nExample 2: Multi-Pattern Query Optimization");
multi_pattern_optimization(&stats)?;
println!("\nExample 3: Index Selection Strategies");
index_selection_demo(&stats)?;
println!("\nExample 4: Performance Comparison");
performance_comparison(&graph, &stats)?;
Ok(())
}
fn populate_sample_data(graph: &Arc<IndexedGraph>) -> Result<(), Box<dyn std::error::Error>> {
for i in 0..100 {
let person = NamedNode::new(format!("http://example.org/person/{i}"))?;
let type_pred = NamedNode::new("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")?;
let name_pred = NamedNode::new("http://xmlns.com/foaf/0.1/name")?;
let knows_pred = NamedNode::new("http://xmlns.com/foaf/0.1/knows")?;
let age_pred = NamedNode::new("http://xmlns.com/foaf/0.1/age")?;
let person_type = NamedNode::new("http://xmlns.com/foaf/0.1/Person")?;
graph.insert(&Triple::new(person.clone(), type_pred, person_type));
graph.insert(&Triple::new(
person.clone(),
name_pred,
Literal::new(format!("Person {i}")),
));
let age = 20 + (i % 50);
graph.insert(&Triple::new(
person.clone(),
age_pred,
Literal::new(format!("{age}")),
));
if i > 0 {
let friend_id = i - 1;
let friend = NamedNode::new(format!("http://example.org/person/{friend_id}"))?;
graph.insert(&Triple::new(person, knows_pred, friend));
}
}
let triple_count = graph.len();
println!("Added {triple_count} triples to the graph");
Ok(())
}
fn basic_pattern_optimization(stats: &Arc<IndexStats>) -> Result<(), Box<dyn std::error::Error>> {
let optimizer = PatternOptimizer::new(stats.clone());
let pattern = AlgebraTriplePattern {
subject: AlgebraTermPattern::Variable(Variable::new("person")?),
predicate: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
)?),
object: AlgebraTermPattern::NamedNode(NamedNode::new("http://xmlns.com/foaf/0.1/Person")?),
};
let plan = optimizer.optimize_patterns(&[pattern])?;
println!("Pattern: ?person rdf:type foaf:Person");
println!("Optimization results:");
println!(" - Estimated cost: {:.2}", plan.total_cost);
println!(" - Selected index: {:?}", plan.patterns[0].1.index_type);
println!(" - Selectivity: {:.4}", plan.patterns[0].1.selectivity);
Ok(())
}
fn multi_pattern_optimization(stats: &Arc<IndexStats>) -> Result<(), Box<dyn std::error::Error>> {
stats.update_predicate_count("http://www.w3.org/1999/02/22-rdf-syntax-ns#type", 100);
stats.update_predicate_count("http://xmlns.com/foaf/0.1/name", 100);
stats.update_predicate_count("http://xmlns.com/foaf/0.1/age", 100);
stats.update_predicate_count("http://xmlns.com/foaf/0.1/knows", 99);
stats.set_total_triples(399);
let optimizer = PatternOptimizer::new(stats.clone());
let patterns = vec![
AlgebraTriplePattern {
subject: AlgebraTermPattern::Variable(Variable::new("person")?),
predicate: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/age",
)?),
object: AlgebraTermPattern::Literal(Literal::new("25")),
},
AlgebraTriplePattern {
subject: AlgebraTermPattern::Variable(Variable::new("person")?),
predicate: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
)?),
object: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/Person",
)?),
},
AlgebraTriplePattern {
subject: AlgebraTermPattern::Variable(Variable::new("person")?),
predicate: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/knows",
)?),
object: AlgebraTermPattern::Variable(Variable::new("friend")?),
},
AlgebraTriplePattern {
subject: AlgebraTermPattern::Variable(Variable::new("friend")?),
predicate: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/name",
)?),
object: AlgebraTermPattern::Variable(Variable::new("friendName")?),
},
];
let plan = optimizer.optimize_patterns(&patterns)?;
println!("Complex query optimization:");
println!("Total estimated cost: {:.2}", plan.total_cost);
println!("\nOptimized execution order:");
for (i, (pattern, strategy)) in plan.patterns.iter().enumerate() {
let step_num = i + 1;
println!("\n{step_num}. Pattern:");
print_pattern(pattern);
println!(" Index: {:?}", strategy.index_type);
println!(" Cost: {:.2}", strategy.estimated_cost);
println!(" Selectivity: {:.4}", strategy.selectivity);
println!(" Binds variables: {:?}", strategy.bound_vars);
}
println!("\nVariable binding progression:");
for (i, bindings) in plan.binding_order.iter().enumerate() {
let step_num = i + 1;
println!(" After step {step_num}: {bindings:?}");
}
Ok(())
}
fn index_selection_demo(stats: &Arc<IndexStats>) -> Result<(), Box<dyn std::error::Error>> {
let optimizer = PatternOptimizer::new(stats.clone());
let scenarios = vec![
(
"Bound subject",
TriplePattern::new(
Some(SubjectPattern::NamedNode(NamedNode::new(
"http://example.org/alice",
)?)),
None,
None,
),
),
(
"Bound predicate",
TriplePattern::new(
None,
Some(PredicatePattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/name",
)?)),
None,
),
),
(
"Bound object",
TriplePattern::new(
None,
None,
Some(ObjectPattern::Literal(Literal::new("Alice"))),
),
),
(
"Bound subject and predicate",
TriplePattern::new(
Some(SubjectPattern::NamedNode(NamedNode::new(
"http://example.org/alice",
)?)),
Some(PredicatePattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/name",
)?)),
None,
),
),
];
for (name, pattern) in scenarios {
let index = optimizer.get_optimal_index(&pattern, &Default::default());
println!("{name}: {index:?}");
}
Ok(())
}
fn performance_comparison(
graph: &Arc<IndexedGraph>,
stats: &Arc<IndexStats>,
) -> Result<(), Box<dyn std::error::Error>> {
let optimizer = PatternOptimizer::new(stats.clone());
let executor = PatternExecutor::new(graph.clone(), stats.clone());
let patterns = vec![
AlgebraTriplePattern {
subject: AlgebraTermPattern::Variable(Variable::new("person")?),
predicate: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/age",
)?),
object: AlgebraTermPattern::Literal(Literal::new("30")),
},
AlgebraTriplePattern {
subject: AlgebraTermPattern::Variable(Variable::new("person")?),
predicate: AlgebraTermPattern::NamedNode(NamedNode::new(
"http://xmlns.com/foaf/0.1/name",
)?),
object: AlgebraTermPattern::Variable(Variable::new("name")?),
},
];
let start = Instant::now();
let plan = optimizer.optimize_patterns(&patterns)?;
let optimization_time = start.elapsed();
let start = Instant::now();
let results = executor.execute_plan(&plan)?;
let execution_time = start.elapsed();
println!("Performance metrics:");
println!(" Optimization time: {optimization_time:?}");
println!(" Execution time: {execution_time:?}");
println!(" Results found: {}", results.len());
if !results.is_empty() {
println!("\nSample results:");
for (i, result) in results.iter().take(3).enumerate() {
let result_num = i + 1;
println!(" Result {result_num}:");
for (var, term) in result {
println!(" ?{var} = {term}");
}
}
}
Ok(())
}
fn print_pattern(pattern: &AlgebraTriplePattern) {
let subject = match &pattern.subject {
AlgebraTermPattern::Variable(v) => format!("?{v}"),
AlgebraTermPattern::NamedNode(n) => format!("<{}>", n.as_str()),
AlgebraTermPattern::BlankNode(b) => format!("_:{}", b.as_str()),
AlgebraTermPattern::Literal(l) => format!("\"{}\"", l.value()),
AlgebraTermPattern::QuotedTriple(_) => "<<RDF-star triple>>".to_string(),
};
let predicate = match &pattern.predicate {
AlgebraTermPattern::Variable(v) => format!("?{v}"),
AlgebraTermPattern::NamedNode(n) => format!("<{}>", n.as_str()),
_ => "???".to_string(),
};
let object = match &pattern.object {
AlgebraTermPattern::Variable(v) => format!("?{v}"),
AlgebraTermPattern::NamedNode(n) => format!("<{}>", n.as_str()),
AlgebraTermPattern::BlankNode(b) => format!("_:{}", b.as_str()),
AlgebraTermPattern::Literal(l) => format!("\"{}\"", l.value()),
AlgebraTermPattern::QuotedTriple(_) => "<<RDF-star triple>>".to_string(),
};
println!(" {subject} {predicate} {object}");
}