Download go/main.go from Snapkitty/quantum-kernel: direct link, hf CLI and curl.
- Browser
- Download file 9.15 kB
-
https://huggingface.co/Snapkitty/quantum-kernel/resolve/main/go/main.go
- Command line
-
hf download hf://Snapkitty/quantum-kernel/go/main.go
-
curl -L -o main.go https://huggingface.co/Snapkitty/quantum-kernel/resolve/main/go/main.go
9.15 kB
| package main | |
| import ( | |
| "fmt" | |
| "math" | |
| "math/rand" | |
| "time" | |
| ) | |
| type Complex64 struct { | |
| Real float32 | |
| Imag float32 | |
| } | |
| type StateVector struct { | |
| data []Complex64 | |
| numQubits int | |
| } | |
| func NewStateVector(n int) *StateVector { | |
| size := 1 << n | |
| data := make([]Complex64, size) | |
| data[0] = Complex64{Real: 1.0, Imag: 0.0} | |
| return &StateVector{data: data, numQubits: n} | |
| } | |
| func (sv *StateVector) Apply1Qubit(q int, u [2][2]Complex64) { | |
| n := sv.numQubits | |
| block := 1 << (q + 1) | |
| stride := 1 << q | |
| for base := 0; base < (1 << n); base += block { | |
| for offset := 0; offset < stride; offset++ { | |
| i0 := base + offset | |
| i1 := i0 + stride | |
| a := sv.data[i0] | |
| b := sv.data[i1] | |
| sv.data[i0] = Complex64{ | |
| Real: u[0][0].Real*a.Real - u[0][0].Imag*a.Imag + u[0][1].Real*b.Real - u[0][1].Imag*b.Imag, | |
| Imag: u[0][0].Real*a.Imag + u[0][0].Imag*a.Real + u[0][1].Real*b.Imag + u[0][1].Imag*b.Real, | |
| } | |
| sv.data[i1] = Complex64{ | |
| Real: u[1][0].Real*a.Real - u[1][0].Imag*a.Imag + u[1][1].Real*b.Real - u[1][1].Imag*b.Imag, | |
| Imag: u[1][0].Real*a.Imag + u[1][0].Imag*a.Real + u[1][1].Real*b.Imag + u[1][1].Imag*b.Real, | |
| } | |
| } | |
| } | |
| } | |
| func (sv *StateVector) Apply2Qubit(q1, q2 int, u [4][4]Complex64) { | |
| n := sv.numQubits | |
| for i := 0; i < (1 << n); i++ { | |
| b1 := (i >> q1) & 1 | |
| b2 := (i >> q2) & 1 | |
| idx := b1*2 + b2 | |
| if idx != 0 { | |
| continue | |
| } | |
| i00 := i | |
| i01 := i | (1 << q2) | |
| i10 := i | (1 << q1) | |
| i11 := i | (1 << q1) | (1 << q2) | |
| indices := [4]int{i00, i01, i10, i11} | |
| var vals [4]Complex64 | |
| for k := 0; k < 4; k++ { | |
| vals[k] = sv.data[indices[k]] | |
| } | |
| for row := 0; row < 4; row++ { | |
| var sum Complex64 | |
| for col := 0; col < 4; col++ { | |
| a := u[row][col] | |
| b := vals[col] | |
| sum.Real += a.Real*b.Real - a.Imag*b.Imag | |
| sum.Imag += a.Real*b.Imag + a.Imag*b.Real | |
| } | |
| sv.data[indices[row]] = sum | |
| } | |
| } | |
| } | |
| func (sv *StateVector) Copy() *StateVector { | |
| newData := make([]Complex64, len(sv.data)) | |
| copy(newData, sv.data) | |
| return &StateVector{data: newData, numQubits: sv.numQubits} | |
| } | |
| func (sv *StateVector) InnerProduct(other *StateVector) Complex64 { | |
| var sum Complex64 | |
| for i := range sv.data { | |
| a := sv.data[i] | |
| b := other.data[i] | |
| sum.Real += a.Real*b.Real + a.Imag*b.Imag | |
| sum.Imag += a.Real*b.Imag - a.Imag*b.Real | |
| } | |
| return sum | |
| } | |
| func RZGate(theta float64) [2][2]Complex64 { | |
| c := float32(math.Cos(theta / 2)) | |
| s := float32(math.Sin(theta / 2)) | |
| return [2][2]Complex64{ | |
| {{Real: c, Imag: -s}, {Real: 0, Imag: 0}}, | |
| {{Real: 0, Imag: 0}, {Real: c, Imag: s}}, | |
| } | |
| } | |
| func RYGate(theta float64) [2][2]Complex64 { | |
| c := float32(math.Cos(theta / 2)) | |
| s := float32(math.Sin(theta / 2)) | |
| return [2][2]Complex64{ | |
| {{Real: c, Imag: 0}, {Real: -s, Imag: 0}}, | |
| {{Real: s, Imag: 0}, {Real: c, Imag: 0}}, | |
| } | |
| } | |
| func CZGate() [4][4]Complex64 { | |
| return [4][4]Complex64{ | |
| {{Real: 1}, {}, {}, {}}, | |
| {{}, {Real: 1}, {}, {}}, | |
| {{}, {}, {Real: 1}, {}}, | |
| {{}, {}, {}, {Real: -1}}, | |
| } | |
| } | |
| type QuantumKernelSVM struct { | |
| NQubits int | |
| NLayers int | |
| Shots int | |
| EntGraph [][2]int | |
| C float64 | |
| Params [][]float64 | |
| } | |
| func NewQuantumKernelSVM(nQubits, nLayers, shots int) *QuantumKernelSVM { | |
| entGraph := make([][2]int, nQubits-1) | |
| for i := 0; i < nQubits-1; i++ { | |
| entGraph[i] = [2]int{i, i + 1} | |
| } | |
| params := make([][]float64, nLayers) | |
| for l := 0; l < nLayers; l++ { | |
| params[l] = make([]float64, 3*nQubits) | |
| for p := 0; p < 3*nQubits; p++ { | |
| params[l][p] = 1.0 + rand.Float64()*0.2 - 0.1 | |
| } | |
| } | |
| return &QuantumKernelSVM{ | |
| NQubits: nQubits, | |
| NLayers: nLayers, | |
| Shots: shots, | |
| EntGraph: entGraph, | |
| C: 1.0, | |
| Params: params, | |
| } | |
| } | |
| func (svm *QuantumKernelSVM) ApplyFeatureMap(sv *StateVector, features []float64) { | |
| for layer := 0; layer < svm.NLayers; layer++ { | |
| for q := 0; q < svm.NQubits; q++ { | |
| x := features[q%len(features)] | |
| tz1 := svm.Params[layer][3*q] | |
| ty := svm.Params[layer][3*q+1] | |
| tz2 := svm.Params[layer][3*q+2] | |
| sv.Apply1Qubit(q, RZGate(2*x*tz1)) | |
| sv.Apply1Qubit(q, RYGate(2*x*ty)) | |
| sv.Apply1Qubit(q, RZGate(2*x*tz2)) | |
| } | |
| for _, edge := range svm.EntGraph { | |
| sv.Apply2Qubit(edge[0], edge[1], CZGate()) | |
| } | |
| } | |
| } | |
| func (svm *QuantumKernelSVM) KernelExact(featuresA, featuresB []float64) float64 { | |
| svA := NewStateVector(svm.NQubits) | |
| svm.ApplyFeatureMap(svA, featuresA) | |
| svB := NewStateVector(svm.NQubits) | |
| svm.ApplyFeatureMap(svB, featuresB) | |
| ip := svA.InnerProduct(svB) | |
| return float64(ip.Real*ip.Real + ip.Imag*ip.Imag) | |
| } | |
| func (svm *QuantumKernelSVM) KernelShots(featuresA, featuresB []float64) float64 { | |
| exact := svm.KernelExact(featuresA, featuresB) | |
| p0 := (1.0 + exact) / 2.0 | |
| countZero := 0 | |
| for s := 0; s < svm.Shots; s++ { | |
| if rand.Float64() < p0 { | |
| countZero++ | |
| } | |
| } | |
| return 2.0*float64(countZero)/float64(svm.Shots) - 1.0 | |
| } | |
| func (svm *QuantumKernelSVM) ComputeKernelMatrix(dataset [][]float64) [][]float64 { | |
| n := len(dataset) | |
| K := make([][]float64, n) | |
| for i := range K { | |
| K[i] = make([]float64, n) | |
| } | |
| for i := 0; i < n; i++ { | |
| for j := i; j < n; j++ { | |
| kij := svm.KernelShots(dataset[i], dataset[j]) | |
| K[i][j] = kij | |
| K[j][i] = kij | |
| } | |
| } | |
| return K | |
| } | |
| func (svm *QuantumKernelSVM) SolveDual(K [][]float64, labels []float64) ([]float64, float64) { | |
| n := len(labels) | |
| alpha := make([]float64, n) | |
| b := 0.0 | |
| for iter := 0; iter < 1000; iter++ { | |
| maxV := 0.0 | |
| for i := 0; i < n; i++ { | |
| grad := 1.0 | |
| for j := 0; j < n; j++ { | |
| grad -= alpha[j] * labels[j] * K[i][j] * labels[i] | |
| } | |
| v := math.Abs(grad) | |
| if v > maxV { | |
| maxV = v | |
| } | |
| alpha[i] = math.Max(0, math.Min(svm.C, alpha[i]+0.01*labels[i]*grad)) | |
| } | |
| if maxV < 1e-4 { | |
| break | |
| } | |
| } | |
| svIndices := []int{} | |
| for i := 0; i < n; i++ { | |
| if alpha[i] > 1e-5 && alpha[i] < svm.C-1e-5 { | |
| svIndices = append(svIndices, i) | |
| } | |
| } | |
| if len(svIndices) > 0 { | |
| bSum := 0.0 | |
| for _, k := range svIndices { | |
| sum := 0.0 | |
| for j := 0; j < n; j++ { | |
| sum += alpha[j] * labels[j] * K[k][j] | |
| } | |
| bSum += labels[k] - sum | |
| } | |
| b = bSum / float64(len(svIndices)) | |
| } | |
| return alpha, b | |
| } | |
| func main() { | |
| rand.Seed(time.Now().UnixNano()) | |
| fmt.Println("============================================================") | |
| fmt.Println("QUANTUM KERNEL SVM — 5 Qubit Hello World (Go Simulator)") | |
| fmt.Println("State Vector Engine | Shot-Based SWAP Test | SMO Solver") | |
| fmt.Println("============================================================") | |
| fmt.Println() | |
| nQubits := 5 | |
| nLayers := 2 | |
| shots := 1000 | |
| svm := NewQuantumKernelSVM(nQubits, nLayers, shots) | |
| fmt.Printf("Qubits: %d | Layers: %d | Shots: %d\n", nQubits, nLayers, shots) | |
| fmt.Printf("Hilbert space dim: 2^%d = %d\n", nQubits, 1<<nQubits) | |
| fmt.Printf("Entanglement: linear chain %v\n", svm.EntGraph) | |
| fmt.Println() | |
| dataset := [][]float64{ | |
| {0, 0, 0, 0, 0}, | |
| {0, 1, 0, 1, 0}, | |
| {1, 0, 1, 0, 1}, | |
| {1, 1, 1, 1, 1}, | |
| {0.5, 0.5, 0.5, 0.5, 0.5}, | |
| {0.2, 0.8, 0.2, 0.8, 0.2}, | |
| {0.8, 0.2, 0.8, 0.2, 0.8}, | |
| {0.3, 0.7, 0.3, 0.7, 0.3}, | |
| } | |
| labels := []float64{-1, 1, 1, -1, -1, 1, 1, -1} | |
| fmt.Printf("Dataset: %d samples, %d features\n", len(dataset), len(dataset[0])) | |
| fmt.Printf("Labels: %v\n", labels) | |
| fmt.Println() | |
| fmt.Println("Computing quantum kernel matrix...") | |
| start := time.Now() | |
| K := svm.ComputeKernelMatrix(dataset) | |
| elapsed := time.Since(start) | |
| fmt.Printf("Done in %v\n\n", elapsed) | |
| fmt.Println("Kernel matrix (4x4 corner):") | |
| for i := 0; i < 4; i++ { | |
| fmt.Printf(" [") | |
| for j := 0; j < 4; j++ { | |
| fmt.Printf(" %7.4f", K[i][j]) | |
| } | |
| fmt.Println(" ]") | |
| } | |
| fmt.Println() | |
| fmt.Println("Training SVM (dual solver)...") | |
| alpha, bias := svm.SolveDual(K, labels) | |
| svCount := 0 | |
| for _, a := range alpha { | |
| if a > 1e-5 { | |
| svCount++ | |
| } | |
| } | |
| fmt.Printf("Support vectors: %d / %d\n", svCount, len(labels)) | |
| fmt.Printf("Bias: %.4f\n\n", bias) | |
| fmt.Println("Predictions:") | |
| correct := 0 | |
| for i := 0; i < len(dataset); i++ { | |
| decision := bias | |
| for j := 0; j < len(dataset); j++ { | |
| decision += alpha[j] * labels[j] * K[j][i] | |
| } | |
| pred := 1.0 | |
| if decision < 0 { | |
| pred = -1.0 | |
| } | |
| match := "OK" | |
| if pred != labels[i] { | |
| match = "MISS" | |
| } else { | |
| correct++ | |
| } | |
| fmt.Printf(" x[%d] -> decision=%.4f, pred=%+.0f, true=%+.0f [%s]\n", i, decision, pred, labels[i], match) | |
| } | |
| fmt.Printf("\nAccuracy: %d / %d = %.1f%%\n", correct, len(labels), 100*float64(correct)/float64(len(labels))) | |
| fmt.Println() | |
| fmt.Println("------------------------------------------------------------") | |
| fmt.Println("Shot noise analysis (kernel[0,1]):") | |
| estimates := make([]float64, 20) | |
| for i := range estimates { | |
| estimates[i] = svm.KernelShots(dataset[0], dataset[1]) | |
| } | |
| mean := 0.0 | |
| for _, e := range estimates { | |
| mean += e | |
| } | |
| mean /= float64(len(estimates)) | |
| variance := 0.0 | |
| for _, e := range estimates { | |
| variance += (e - mean) * (e - mean) | |
| } | |
| variance /= float64(len(estimates)) | |
| exact := svm.KernelExact(dataset[0], dataset[1]) | |
| fmt.Printf(" Mean: %.6f\n", mean) | |
| fmt.Printf(" Std: %.6f\n", math.Sqrt(variance)) | |
| fmt.Printf(" Exact: %.6f\n", exact) | |
| fmt.Println() | |
| fmt.Println("============================================================") | |
| fmt.Println("HELLO WORLD COMPLETE — 5 qubit quantum kernel executed") | |
| fmt.Println("============================================================") | |
| } | |