Skip to main content

Find Weighted Shortest Paths with Dijkstra’s Algorithm  

ShortestPathDijkstras finds the optimal shortest path in weighted graphs using Dijkstra’s algorithm. It supports sophisticated weight calculations that can reference edge properties, source node properties, and destination node properties, making it incredibly flexible for real-world routing scenarios.
::ShortestPathDijkstras<EdgeType>(weight_expression)
::To(target_id)
When using the SDKs or curling the endpoint, the query name must match what is defined in the queries.hx file exactly.

How It Works

Dijkstra’s algorithm:
  1. Starts at the source node with distance 0
  2. Explores neighbors, calculating cumulative path weights
  3. Always processes the node with the smallest known distance next
  4. Guarantees finding the optimal shortest path for non-negative weights
All weights must be non-negative. Negative weights can produce incorrect results or infinite loops.

When to Use ShortestPathDijkstras

Use Dijkstra when you need:
  • Weighted paths: Edges have different costs (distance, time, bandwidth)
  • Custom calculations: Combine multiple properties into path weights
  • Multi-factor routing: Consider traffic, reliability, cost simultaneously
  • Property-based weights: Use node or edge properties in calculations
  • Flexibility: Maximum control over what defines “shortest”

Weight Expressions

Weight expressions can reference:
  • _::{property} - Edge property
  • _::FromN::{property} - Source node property
  • _::ToN::{property} - Destination node property
  • Mathematical functions: ADD, MUL, DIV, SUB, POW, SQRT, etc.

Example 1: Simple property-based weight

QUERY FindShortestRoute(start_id: ID, end_id: ID) =>
    result <- N<City>(start_id)
        ::ShortestPathDijkstras<Road>(_::{distance})
        ::To(end_id)
    RETURN result

QUERY CreateCity(name: String, population: I64) =>
    city <- CREATE V<City> { name: name, population: population }
    RETURN city

QUERY CreateRoad(from_id: ID, to_id: ID, distance: F64, traffic_level: F64) =>
    road <- CREATE E<Road>(from_id, to_id) {
        distance: distance,
        traffic_level: traffic_level
    }
    RETURN road
Here’s how to run the query using the SDKs or curl
from helix.client import Client

client = Client(local=True, port=6969)

# Create cities
cities = {}
city_data = [
    ("Los Angeles", 4000000),
    ("San Diego", 1400000),
    ("Phoenix", 1600000),
    ("Las Vegas", 650000),
]

for name, population in city_data:
    result = client.query("CreateCity", {"name": name, "population": population})
    cities[name] = result["city"]["id"]

# Create road network with distances
roads = [
    ("Los Angeles", "San Diego", 120.0, 0.7),
    ("Los Angeles", "Las Vegas", 270.0, 0.5),
    ("San Diego", "Phoenix", 355.0, 0.4),
    ("Las Vegas", "Phoenix", 297.0, 0.6),
]

for from_city, to_city, distance, traffic in roads:
    client.query("CreateRoad", {
        "from_id": cities[from_city],
        "to_id": cities[to_city],
        "distance": distance,
        "traffic_level": traffic
    })

# Find shortest route by distance
result = client.query("FindShortestRoute", {
    "start_id": cities["Los Angeles"],
    "end_id": cities["Phoenix"]
})

print(f"Shortest route from LA to Phoenix:")
print(f"Path: {' -> '.join([node['name'] for node in result['result']['path']])}")
print(f"Total distance: {result['result']['total_weight']:.1f} miles")
print(f"Hops: {result['result']['hop_count']}")

Example 2: Traffic-aware routing with multi-context weights

QUERY FindTrafficAwareRoute(start_id: ID, end_id: ID) =>
    result <- N<City>(start_id)
        ::ShortestPathDijkstras<Road>(MUL(_::{distance}, _::FromN::{traffic_factor}))
        ::To(end_id)
    RETURN result

QUERY CreateCityWithTraffic(name: String, traffic_factor: F64) =>
    city <- CREATE V<City> { name: name, traffic_factor: traffic_factor }
    RETURN city

QUERY CreateRoad(from_id: ID, to_id: ID, distance: F64) =>
    road <- CREATE E<Road>(from_id, to_id) { distance: distance }
    RETURN road
Here’s how to run the query using the SDKs or curl
from helix.client import Client

client = Client(local=True, port=6969)

# Create cities with traffic factors
cities = {}
city_data = [
    ("Downtown", 2.5),      # Heavy traffic
    ("Suburbs", 1.0),       # Normal traffic
    ("Industrial", 1.2),    # Light traffic
    ("Airport", 1.8),       # Moderate traffic
]

for name, traffic_factor in city_data:
    result = client.query("CreateCityWithTraffic", {
        "name": name,
        "traffic_factor": traffic_factor
    })
    cities[name] = result["city"]["id"]

# Create roads (base distances)
roads = [
    ("Downtown", "Suburbs", 10.0),
    ("Downtown", "Industrial", 8.0),
    ("Suburbs", "Airport", 15.0),
    ("Industrial", "Airport", 12.0),
]

for from_city, to_city, distance in roads:
    client.query("CreateRoad", {
        "from_id": cities[from_city],
        "to_id": cities[to_city],
        "distance": distance
    })

# Find traffic-aware route
# Weight = distance * source_traffic_factor
# Avoids routes starting from high-traffic areas
result = client.query("FindTrafficAwareRoute", {
    "start_id": cities["Downtown"],
    "end_id": cities["Airport"]
})

print(f"Traffic-aware route from Downtown to Airport:")
print(f"Path: {' -> '.join([node['name'] for node in result['result']['path']])}")
print(f"Effective distance: {result['result']['total_weight']:.1f}")

Example 3: Complex multi-factor weight calculation

QUERY FindOptimalRoute(start_id: ID, end_id: ID) =>
    result <- N<Location>(start_id)
        ::ShortestPathDijkstras<Route>(
            ADD(
                MUL(_::{distance}, 0.4),
                ADD(
                    MUL(_::FromN::{traffic_factor}, 0.3),
                    MUL(SUB(1, _::{reliability}), 0.3)
                )
            )
        )
        ::To(end_id)
    RETURN result

QUERY CreateLocation(name: String, traffic_factor: F64) =>
    location <- CREATE V<Location> { name: name, traffic_factor: traffic_factor }
    RETURN location

QUERY CreateRoute(from_id: ID, to_id: ID, distance: F64, reliability: F64) =>
    route <- CREATE E<Route>(from_id, to_id) {
        distance: distance,
        reliability: reliability
    }
    RETURN route
Here’s how to run the query using the SDKs or curl
from helix.client import Client

client = Client(local=True, port=6969)

# Create locations with traffic factors
locations = {}
location_data = [
    ("Station A", 1.2),
    ("Station B", 0.8),
    ("Station C", 1.5),
    ("Station D", 1.0),
]

for name, traffic_factor in location_data:
    result = client.query("CreateLocation", {
        "name": name,
        "traffic_factor": traffic_factor
    })
    locations[name] = result["location"]["id"]

# Create routes with distance and reliability
# Weight = 0.4*distance + 0.3*traffic + 0.3*(1-reliability)
routes = [
    ("Station A", "Station B", 100.0, 0.95),
    ("Station A", "Station C", 80.0, 0.70),
    ("Station B", "Station D", 120.0, 0.90),
    ("Station C", "Station D", 90.0, 0.85),
]

for from_loc, to_loc, distance, reliability in routes:
    client.query("CreateRoute", {
        "from_id": locations[from_loc],
        "to_id": locations[to_loc],
        "distance": distance,
        "reliability": reliability
    })

# Find optimal route considering distance, traffic, and reliability
result = client.query("FindOptimalRoute", {
    "start_id": locations["Station A"],
    "end_id": locations["Station D"]
})

print(f"Optimal route from Station A to Station D:")
print(f"Path: {' -> '.join([node['name'] for node in result['result']['path']])}")
print(f"Composite weight: {result['result']['total_weight']:.2f}")
print(f"(40% distance + 30% traffic + 30% unreliability)")

Property Context Reference

ContextDescriptionExample
_::{property}Edge property_::{distance}
_::FromN::{property}Source node property_::FromN::{traffic_factor}
_::ToN::{property}Destination node property_::ToN::{popularity}

Available Mathematical Functions

Use these functions in weight expressions:
  • Arithmetic: ADD, SUB, MUL, DIV, MOD
  • Power: POW, SQRT, EXP, LN, LOG
  • Rounding: CEIL, FLOOR, ROUND, ABS
  • Trigonometric: SIN, COS, TAN
  • Constants: PI()
See Advanced Weight Expressions for more details.

Performance Considerations

  • Time Complexity: O((V + E) log V) using binary heap
  • Space Complexity: O(V) for distance tracking
  • Weight Calculation: Evaluated once per edge during exploration
  • Indexing: Index properties used in weight calculations for best performance
Complex weight expressions may impact query performance. Profile your queries and consider caching frequently-accessed property values.