Snapkitty/quantum-kernel
0
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 