Skip to the content.

Getting Started with FSharp.Azure.Quantum.Topological

A quick guide to install, build, and run your first topological quantum computation. Aimed at senior .NET and F# developers – no quantum physics PhD required.

Time to first working program: ~5 minutes


Prerequisites

Build and Test

# Clone the repository
git clone https://github.com/Thorium/FSharp.Azure.Quantum.git
cd FSharp.Azure.Quantum

# Build the topological library
dotnet build src/FSharp.Azure.Quantum.Topological/FSharp.Azure.Quantum.Topological.fsproj

# Run the test suite (about a thousand tests)
dotnet test tests/FSharp.Azure.Quantum.Topological.Tests/FSharp.Azure.Quantum.Topological.Tests.fsproj

Your First Computation

Option A: Using the computation expression builder

Create a file MyFirstTopological.fsx:

#r "src/FSharp.Azure.Quantum/bin/Debug/net10.0/FSharp.Azure.Quantum.dll"
#r "src/FSharp.Azure.Quantum.Topological/bin/Debug/net10.0/FSharp.Azure.Quantum.Topological.dll"

open FSharp.Azure.Quantum.Topological

// Create a backend -- a classical simulator for Ising anyons, allowing up to 10 anyons
let backend = TopologicalUnifiedBackendFactory.createIsing 10

// Write a topological program using the computation expression
let bellProgram = topological backend {
    // Initialize 2 logical qubits: 6 sigma anyons (one pair per qubit plus a parity pair)
    do! TopologicalBuilder.initialize AnyonSpecies.AnyonType.Ising 2

    // Braid anyons 0 and 1 (inside qubit 0's pair: adds a phase)
    do! TopologicalBuilder.braid 0

    // Braid anyons 2 and 3 (inside qubit 1's pair: adds a phase)
    do! TopologicalBuilder.braid 2

    // Braid anyons 1 and 2 (across the two pairs: entangles the qubits)
    do! TopologicalBuilder.braid 1

    // Measure fusion of the first pair: Vacuum (qubit 0 = 0) or Psi (qubit 0 = 1)
    let! outcome = TopologicalBuilder.measure 0
    return outcome
}

// Execute and handle the result
let result =
    TopologicalBuilder.execute backend bellProgram
    |> Async.AwaitTask |> Async.RunSynchronously

match result with
| Ok outcome -> printfn "Fusion outcome: %A" outcome
| Error err  -> printfn "Error: %s" err.Message

Preferred async pattern: Use task { } for non-blocking execution:

task {
    let! result = TopologicalBuilder.execute backend bellProgram
    match result with
    | Ok outcome -> printfn "Fusion outcome: %A" outcome
    | Error err  -> printfn "Error: %s" err.Message
}

Run it:

dotnet fsi MyFirstTopological.fsx

Option B: Using the backend API directly

#r "src/FSharp.Azure.Quantum/bin/Debug/net10.0/FSharp.Azure.Quantum.dll"
#r "src/FSharp.Azure.Quantum.Topological/bin/Debug/net10.0/FSharp.Azure.Quantum.Topological.dll"

open FSharp.Azure.Quantum.Core
open FSharp.Azure.Quantum.Core.BackendAbstraction
open FSharp.Azure.Quantum.Topological

// Create a unified backend (implements IQuantumBackend)
let backend = TopologicalUnifiedBackendFactory.createIsing 10

// Use the synchronous IQuantumBackend API: 2 logical qubits
match backend.InitializeState 2 with
| Ok initialState ->
    // Apply a native braid operation (no gate compilation involved)
    match backend.ApplyOperation (QuantumOperation.Braid 1) initialState with
    | Ok braidedState ->
        // Sample 100 shots in the computational basis
        let measurements = QuantumState.measure braidedState 100
        printfn "First shots: %A" (Array.truncate 5 measurements)
    | Error e -> printfn "Braid error: %s" e.Message
| Error e -> printfn "Init error: %s" e.Message

Gates work too: backend.ApplyOperation (QuantumOperation.Gate (CircuitBuilder.H 0)) state compiles the gate to braids on the fly.

Option C: Pure mathematical exploration (no backend needed)

#r "src/FSharp.Azure.Quantum.Topological/bin/Debug/net10.0/FSharp.Azure.Quantum.Topological.dll"

open FSharp.Azure.Quantum.Topological

let ising = AnyonSpecies.AnyonType.Ising
let sigma = AnyonSpecies.Particle.Sigma

// What happens when two sigma anyons fuse?
let channels = FusionRules.channels sigma sigma ising
printfn "sigma x sigma = %A" channels
// Output: Ok [Vacuum; Psi] -- two possible outcomes, this is a qubit!

// What is the quantum dimension of a sigma anyon?
let d = AnyonSpecies.quantumDimension sigma
printfn "d_sigma = %.4f" d
// Output: 1.4142 (sqrt 2)

// What phase does braiding add?
let R = BraidingOperators.element sigma sigma AnyonSpecies.Particle.Vacuum ising
printfn "R^{sigma,sigma}_vacuum = %A" R
// Output: Ok (0.9238..., -0.3826...) -- the complex number e^(-i*pi/8)

Key Concepts in 60 Seconds

Concept What it means Library type
Anyon A quasiparticle in 2D with exotic exchange statistics AnyonSpecies.Particle
Fusion Combining two anyons – the result is non-deterministic (this encodes a qubit) FusionRules.channels
Braiding Moving anyons around each other – applies a topological phase (this is a gate) BraidingOperators.element
Fusion tree The data structure representing the quantum state FusionTree
Backend Executes topological operations (unified: TopologicalUnifiedBackend via IQuantumBackend) TopologicalUnifiedBackendFactory

Why topological? Information is stored in the topology of anyon worldlines rather than in local degrees of freedom. In theory, local noise cannot change global topology, so errors are suppressed exponentially in the anyon separation. This library is a classical simulator of that model; it does not demonstrate the protection on hardware.

Run the Built-in Examples

The examples/Topological/ directory has 10 runnable scripts:

# Start here -- basic fusion rules
dotnet fsi examples/Topological/BasicFusion.fsx

# Bell state via braiding
dotnet fsi examples/Topological/BellState.fsx

# Knot invariants
dotnet fsi examples/Topological/KauffmanJones.fsx

# Magic state distillation (T-gate for Ising universality)
dotnet fsi examples/Topological/MagicStateDistillation.fsx

# All examples accept CLI flags:
dotnet fsi examples/Topological/BasicFusion.fsx -- --example 3 --trials 500
dotnet fsi examples/Topological/BasicFusion.fsx -- --help

Error Handling

The library uses railway-oriented programming. The mathematical modules (FusionRules, BraidingOperators, FusionTree, TopologicalOperations, …) return TopologicalResult<'T>, which is Result<'T, TopologicalError>:

open FSharp.Azure.Quantum.Topological

// The cases of TopologicalError (each has a .Message and a .Category)
let describe (err: TopologicalError) =
    match err with
    | TopologicalError.ValidationError(field, reason) -> $"bad input {field}: {reason}"
    | TopologicalError.NotImplemented(feature, hint) -> $"not implemented: {feature}"
    | TopologicalError.LogicError(operation, reason) -> $"impossible {operation}: {reason}"
    | TopologicalError.BackendError(backend, reason) -> $"backend {backend}: {reason}"
    | TopologicalError.ComputationError(operation, context) -> $"{operation} failed: {context}"
    | TopologicalError.Other message -> message

The backend (IQuantumBackend) and the topological { } builder report the core library’s QuantumError instead. Use Result.bind / Result.map for composition, or the topologicalResult { } computation expression for sequential error propagation over TopologicalResult values.

  1. Developer Deep Dive – Full guide covering architecture, practical F# patterns, anyon theory, and braiding operations
  2. Architecture Guide – Layered design, module dependencies, design principles
  3. Universal Quantum Computation – How magic state distillation makes Ising anyons universal
  4. Source README – Module reference and complete feature list

Coming from Gate-Based Quantum Computing?

If you already know Qiskit, Q#, or Cirq, here is the mapping:

Gate-Based Topological Equivalent Library API
Qubit Pair of sigma anyons backend.InitializeState 2 (2 qubits = 6 Ising anyons, including a parity pair)
Gate (H, CNOT) Braid operation backend.ApplyOperation (QuantumOperation.Braid index) state
Measurement Fusion measurement QuantumState.measure state shots
Circuit Braid sequence topological backend { ... }
State vector Fusion tree superposition FusionTree + TopologicalOperations.Superposition
Algorithm Algorithm extension AlgorithmExtensions.searchSingleWithTopology etc.