Hone logo
Hone
Problems

Type-Level Maximum Flow in TypeScript

This challenge involves implementing a maximum flow algorithm at the TypeScript type level. You will represent a directed graph with capacities as a type, and your solution will be a type that computes the maximum flow from a specified source to a sink. This exercise explores the expressive power of TypeScript's type system for solving algorithmic problems.

Problem Description

The goal is to create a TypeScript type, MaxFlow<Graph, Source, Sink>, that statically computes the maximum flow value from a Source node to a Sink node within a given Graph. The graph and its capacities will be defined using TypeScript's type system.

Key Requirements:

  1. Graph Representation: The graph will be represented as a tuple of edge objects. Each edge object will define:

    • from: The starting node of the edge.
    • to: The ending node of the edge.
    • capacity: The maximum flow that can pass through this edge.
    • Nodes will be represented by string literals.
  2. Maximum Flow Computation: The MaxFlow type should implement a maximum flow algorithm (e.g., Ford-Fulkerson or Edmonds-Karp, but adapted for type-level computation) to find the maximum flow.

  3. Output: The MaxFlow type should resolve to a union of numbers, where each number represents a possible flow value. The largest number in this union will be the maximum flow.

  4. Iterative Refinement: The type-level computation will likely involve an iterative process of finding augmenting paths and updating residual capacities. This can be achieved using recursive conditional types.

Expected Behavior:

Given a graph definition, a source node, and a sink node, the MaxFlow type should, at compile time, determine the maximum possible flow from the source to the sink.

Edge Cases:

  • Graphs with no path from source to sink.
  • Graphs with zero capacity edges.
  • Graphs with cycles.
  • Source and sink being the same node.

Examples

Example 1: A simple path

type SimpleGraph = [
  { from: 'A'; to: 'B'; capacity: 10 },
  { from: 'B'; to: 'C'; capacity: 5 }
];

// Expected: MaxFlow<SimpleGraph, 'A', 'C'> should resolve to 5

Example 2: Multiple paths

type MultiPathGraph = [
  { from: 'S'; to: 'A'; capacity: 10 },
  { from: 'S'; to: 'B'; capacity: 5 },
  { from: 'A'; to: 'T'; capacity: 10 },
  { from: 'B'; to: 'T'; capacity: 5 }
];

// Expected: MaxFlow<MultiPathGraph, 'S', 'T'> should resolve to 15

Example 3: Bottleneck capacity

type BottleneckGraph = [
  { from: 'S'; to: 'A'; capacity: 10 },
  { from: 'S'; to: 'B'; capacity: 10 },
  { from: 'A'; to: 'C'; capacity: 5 },
  { from: 'B'; to: 'C'; capacity: 10 },
  { from: 'C'; to: 'T'; capacity: 10 }
];

// Expected: MaxFlow<BottleneckGraph, 'S', 'T'> should resolve to 15

Example 4: No path

type NoPathGraph = [
  { from: 'A'; to: 'B'; capacity: 10 }
];

// Expected: MaxFlow<NoPathGraph, 'A', 'C'> should resolve to 0

Constraints

  • The number of nodes and edges will be relatively small (e.g., up to 10 nodes and 20 edges) to remain within TypeScript's type computation limits.
  • Capacities will be positive integers up to 100.
  • Node names will be short string literals.
  • The MaxFlow type should ideally terminate within a reasonable number of type instantiations.

Notes

  • This challenge requires a deep understanding of conditional types, tuple manipulation, and recursive type definitions in TypeScript.
  • Consider how to represent and update residual graphs at the type level.
  • Think about how to find augmenting paths using type-level pattern matching and filtering.
  • The problem is designed to be challenging and may require significant experimentation with TypeScript's type system.
  • Success looks like having a MaxFlow type that correctly computes the maximum flow for the provided examples and satisfies the constraints.
Loading editor...
typescript