CoolFace
Modelpublic

Snapkitty/quantum-kernel

sourceHugging Faceupdated 19d agoView on Hugging Face
0likes
braid_diff.jl210 linesDownload Raw Back to julia
1# braid_diff.jl — Differentiable Artin Generators on Heavy-Hex2 3module BraidDiff4 5using LinearAlgebra6using Random7 8export BraidWord, braid_to_circuit, gumbel_softmax_braid, markov_loss9export apply_braid_relations10 11# ═══════════════════════════════════════════════════════════════════════12# Types13# ═══════════════════════════════════════════════════════════════════════14 15struct BraidWord16    generators::Vector{Int}17    edge_indices::Vector{Int}18    n_strands::Int19end20 21BraidWord(n_strands::Int) = BraidWord(Int[], Int[], n_strands)22 23const HERON_EDGES_0 = [24    (0, 1), (1, 2),25    (0, 3), (1, 3), (1, 4), (2, 4), (2, 5),26    (3, 4), (4, 5), (5, 6),27    (3, 7), (4, 7), (4, 8), (5, 8), (5, 9), (6, 9),28    (7, 8), (8, 9)29]30 31const HERON_EDGE_INDEX = Dict(edge => i for (i, edge) in enumerate(HERON_EDGES_0))32 33# ═══════════════════════════════════════════════════════════════════════34# Braid Word Operations35# ═══════════════════════════════════════════════════════════════════════36 37Base.length(bw::BraidWord) = length(bw.generators)38 39function Base.:(==)(bw1::BraidWord, bw2::BraidWord)40    bw1.generators == bw2.generators && bw1.edge_indices == bw2.edge_indices41end42 43function Base.hash(bw::BraidWord, h::UInt)44    hash(bw.generators, hash(bw.edge_indices, hash(bw.n_strands, h)))45end46 47function Base.inv(bw::BraidWord)::BraidWord48    BraidWord(reverse(-bw.generators), reverse(bw.edge_indices), bw.n_strands)49end50 51function Base.:*(bw1::BraidWord, bw2::BraidWord)::BraidWord52    @assert bw1.n_strands == bw2.n_strands53    BraidWord(vcat(bw1.generators, bw2.generators),54              vcat(bw1.edge_indices, bw2.edge_indices),55              bw1.n_strands)56end57 58# ═══════════════════════════════════════════════════════════════════════59# Braid → Circuit (CX/H sequences on Heron edges)60# ═══════════════════════════════════════════════════════════════════════61 62struct BraidCircuitOp63    gate::String64    qubits::Vector{Int}65    params::Vector{Float64}66end67 68"""69    braid_to_circuit_ops(bw::BraidWord, n_qubits::Int) -> Vector{BraidCircuitOp}70 71Map Artin generators to SWAP/CX sequences on Heron edges.72σ_i → H(t) · CX(c,t) · H(t) · CX(c,t) · H(t)73σ_i⁻¹ → inverse sequence74"""75function braid_to_circuit_ops(bw::BraidWord, n_qubits::Int)::Vector{BraidCircuitOp}76    ops = BraidCircuitOp[]77 78    for (gen, edge_idx) in zip(bw.generators, bw.edge_indices)79        if edge_idx > length(HERON_EDGES_0)80            continue81        end82        q1, q2 = HERON_EDGES_0[edge_idx]83        if q1 >= n_qubits || q2 >= n_qubits84            continue85        end86 87        if gen > 088            push!(ops, BraidCircuitOp("H", [q2], Float64[]))89            push!(ops, BraidCircuitOp("CX", [q1, q2], Float64[]))90            push!(ops, BraidCircuitOp("H", [q2], Float64[]))91            push!(ops, BraidCircuitOp("CX", [q1, q2], Float64[]))92            push!(ops, BraidCircuitOp("H", [q2], Float64[]))93        else94            push!(ops, BraidCircuitOp("H", [q2], Float64[]))95            push!(ops, BraidCircuitOp("CX", [q2, q1], Float64[]))96            push!(ops, BraidCircuitOp("H", [q2], Float64[]))97            push!(ops, BraidCircuitOp("CX", [q2, q1], Float64[]))98            push!(ops, BraidCircuitOp("H", [q2], Float64[]))99        end100    end101 102    return ops103end104 105# ═══════════════════════════════════════════════════════════════════════106# Gumbel-Softmax Braid (Differentiable Selection)107# ═══════════════════════════════════════════════════════════════════════108 109"""110    gumbel_softmax_braid(logits, τ=1.0)111 112Differentiable braid generator selection via Gumbel-Softmax.113logits: [n_generators, n_positions]114"""115function gumbel_softmax_braid(logits::Matrix{Float64}, τ::Float64=1.0)::BraidWord116    n_gens, n_pos = size(logits)117    generators = Int[]118    edge_indices = Int[]119 120    for pos in 1:n_pos121        gumbel = -log.(-log.(rand(n_gens) .+ 1e-20) .+ 1e-20)122        y = (logits[:, pos] .+ gumbel) ./ τ123        y_max = maximum(y)124        probs = exp.(y .- y_max) ./ sum(exp.(y .- y_max))125 126        gen_idx = argmax(probs)127        sign = rand() < 0.5 ? 1 : -1128 129        push!(generators, sign * gen_idx)130        if gen_idx <= length(HERON_EDGES_0)131            edge = HERON_EDGES_0[gen_idx]132            push!(edge_indices, HERON_EDGE_INDEX[edge])133        else134            push!(edge_indices, 1)135        end136    end137 138    BraidWord(generators, edge_indices, n_gens + 1)139end140 141# ═══════════════════════════════════════════════════════════════════════142# Markov Loss143# ═══════════════════════════════════════════════════════════════════════144 145function markov_loss(bw::BraidWord, kernel_fidelity::Float64, gate_count::Int;146                      λ_length::Float64=0.01, λ_gates::Float64=0.001)::Float64147    length_penalty = λ_length * length(bw)148    gate_penalty = λ_gates * gate_count149    return -kernel_fidelity + length_penalty + gate_penalty150end151 152# ═══════════════════════════════════════════════════════════════════════153# Braid Group Relations (Artin Presentation)154# ═══════════════════════════════════════════════════════════════════════155 156function shares_vertex(e1::Int, e2::Int)::Bool157    if e1 > length(HERON_EDGES_0) || e2 > length(HERON_EDGES_0)158        return false159    end160    q1a, q1b = HERON_EDGES_0[e1]161    q2a, q2b = HERON_EDGES_0[e2]162    return q1a == q2a || q1a == q2b || q1b == q2a || q1b == q2b163end164 165"""166    apply_braid_relations(bw::BraidWord)167 168Apply Artin relations:1691. σ_i σ_j = σ_j σ_i for |i-j| > 1 (far commutativity)1702. σ_i σ_{i+1} σ_i = σ_{i+1} σ_i σ_{i+1} (braid relation)171"""172function apply_braid_relations(bw::BraidWord)::BraidWord173    gens = copy(bw.generators)174    edges = copy(bw.edge_indices)175    changed = true176 177    while changed178        changed = false179        i = 1180        while i <= length(gens) - 1181            e1, e2 = edges[i], edges[i+1]182 183            if !shares_vertex(e1, e2)184                gens[i], gens[i+1] = gens[i+1], gens[i]185                edges[i], edges[i+1] = edges[i+1], edges[i]186                changed = true187                i += 1188            elseif shares_vertex(e1, e2) && i <= length(gens) - 2189                g1, g3 = gens[i], gens[i+2]190                e3 = edges[i+2]191                if g1 == g3 && e1 == e3192                    g2 = gens[i+1]193                    gens[i], gens[i+1], gens[i+2] = g2, g1, g2194                    edges[i], edges[i+1], edges[i+2] = e2, e1, e2195                    changed = true196                    i += 2197                else198                    i += 1199                end200            else201                i += 1202            end203        end204    end205 206    BraidWord(gens, edges, bw.n_strands)207end208 209end # module BraidDiff210