diff --git a/examples/qaoa_example.ipynb b/examples/qaoa_example.ipynb index c242b96..4a5f47e 100644 --- a/examples/qaoa_example.ipynb +++ b/examples/qaoa_example.ipynb @@ -34,18 +34,7 @@ "cell_type": "code", "execution_count": 2, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Info: Precompiling Plots [91a5bcdd-55d7-5caf-9e0b-520d859cae80]\n", - "└ @ Base loading.jl:1278\n", - "┌ Info: Precompiling LaTeXStrings [b964fa9f-0449-5b57-a5c2-d3ea65f4040f]\n", - "└ @ Base loading.jl:1278\n" - ] - } - ], + "outputs": [], "source": [ "# visualization\n", "using Plots\n", @@ -71,7 +60,11 @@ ] }, { - "attachments": {}, + "attachments": { + "068aa9dd-70e5-4795-9d06-958de47c874b.png": { + "image/png": "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" + } + }, "cell_type": "markdown", "metadata": {}, "source": [ @@ -81,7 +74,11 @@ ] }, { - "attachments": {}, + "attachments": { + "b9a93210-395f-4bad-9d8b-541b45f624c9.png": { + "image/png": "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" + } + }, "cell_type": "markdown", "metadata": {}, "source": [ @@ -163,7 +160,7 @@ "outputs": [], "source": [ "# define uniform superposition state s\n", - "s_uni = fill(1/√(2^n) + 0.0im, 2^n);" + "s_uni = convert(Vector{ComplexQ}, fill(1/√(2^n) + 0.0im, 2^n));" ] }, { @@ -245,7 +242,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "diag(Cmat) = Complex{Float64}[0.0 + 0.0im, 1.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 4.0 + 0.0im, 5.0 - 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 5.0 - 0.0im, 4.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 1.0 + 0.0im, 0.0 + 0.0im]\n" + "diag(Cmat) = ComplexF64[0.0 + 0.0im, 1.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 4.0 + 0.0im, 5.0 - 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 5.0 - 0.0im, 4.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 3.0 + 0.0im, 2.0 + 0.0im, 2.0 + 0.0im, 3.0 + 0.0im, 1.0 + 0.0im, 0.0 + 0.0im]\n" ] } ], @@ -299,8 +296,8 @@ { "data": { "text/plain": [ - "1-element Array{Float64,1}:\n", - " 2.499208652309536" + "1-element Vector{Float32}:\n", + " 2.499939" ] }, "execution_count": 8, @@ -329,9 +326,9 @@ "name": "stdout", "output_type": "stream", "text": [ - "apply(s_uni, circ1) = [2.5001403700650973]\n", - "apply(s_uni, circ1) = [3.9999999999999973]\n", - "apply(s_uni, circ1) = [4.0]\n" + "apply(s_uni, circ1) = Float32[2.50052]\n", + "apply(s_uni, circ1) = Float32[3.999999]\n", + "apply(s_uni, circ1) = Float32[3.9999993]\n" ] } ], @@ -384,452 +381,484 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", "\n" ] }, @@ -852,11 +881,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "apply(s_uni, circ2) = [2.5002312727553515]\n", - "apply(s_uni, circ2) = [4.999920933578631]\n", - "apply(s_uni, circ2) = [4.9999384211975295]\n", - "apply(s_uni, circ2) = [4.999949989885429]\n", - "apply(s_uni, circ2) = [4.9999587023966185]\n" + "apply(s_uni, circ2) = Float32[2.501162]\n", + "apply(s_uni, circ2) = Float32[4.9998145]\n", + "apply(s_uni, circ2) = Float32[4.999973]\n", + "apply(s_uni, circ2) = Float32[4.999996]\n", + "apply(s_uni, circ2) = Float32[4.9999986]\n" ] } ], @@ -902,457 +931,489 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", "\n" ] }, @@ -1376,15 +1437,15 @@ ], "metadata": { "kernelspec": { - "display_name": "Julia 1.5.4", + "display_name": "Julia 1.7.0", "language": "julia", - "name": "julia-1.5" + "name": "julia-1.7" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.5.4" + "version": "1.7.0" } }, "nbformat": 4, diff --git a/examples/training_example1.ipynb b/examples/training_example1.ipynb index 20774b7..b6a2900 100644 --- a/examples/training_example1.ipynb +++ b/examples/training_example1.ipynb @@ -17,6 +17,7 @@ "metadata": {}, "outputs": [], "source": [ + "using Qaintessent\n", "using Qaintellect\n", "using LinearAlgebra\n", "using Flux\n", @@ -57,14 +58,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "rx = RxGate([0.2852979630949063])\n", - "ry = RyGate([5.897114323717471])\n" + "rx = RxGate(Float32[0.2345506])\n", + "ry = RyGate(Float32[4.734649])\n" ] }, { "data": { "text/plain": [ - "RyGate([5.897114323717471])" + "RyGate(Float32[4.734649])" ] }, "execution_count": 2, @@ -132,15 +133,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "ψ = Complex{Float64}[1.0 + 0.0im, 0.0 + 0.0im]\n" + "ψ = ComplexF32[1.0f0 + 0.0f0im, 0.0f0 + 0.0f0im]\n" ] }, { "data": { "text/plain": [ - "2-element Array{Complex{Float64},1}:\n", - " 1.0 + 0.0im\n", - " 0.0 + 0.0im" + "2-element Vector{ComplexF32}:\n", + " 1.0f0 + 0.0f0im\n", + " 0.0f0 + 0.0f0im" ] }, "execution_count": 4, @@ -149,7 +150,7 @@ } ], "source": [ - "ψ = ComplexF64[1, 0]\n", + "ψ = ComplexQ[1, 0]\n", "e = -1\n", "@show(ψ)" ] @@ -170,9 +171,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "paras = Params([[0.2852979630949063], [5.897114323717471], \n", - " [1, 1] = 1.0+0.0im\n", - " [2, 2] = -1.0+0.0im])\n" + "paras = Params([Float32[0.2345506], Float32[4.734649], sparse([1, 2], [1, 2], ComplexF32[1.0f0 + 0.0f0im, -1.0f0 + 0.0f0im], 2, 2)])\n" ] }, { @@ -188,7 +187,7 @@ ], "source": [ "# create loss function: note that circuit `c` is applied to `x`\n", - "loss(x, y) = Flux.mse(c(x), y)\n", + "loss(x, y) = Flux.mse(apply(x, c), y)\n", "\n", "# gather parameters from Circuit\n", "paras = Flux.params(c)\n", @@ -212,8 +211,8 @@ { "data": { "text/plain": [ - "1-element Array{Float64,1}:\n", - " 1.3650695278938842" + "1-element Vector{Float32}:\n", + " 1.9868569" ] }, "execution_count": 6, @@ -243,7 +242,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "loss(ψ, e) = 2.094566636677492\n" + "loss(ψ, e) = 0.4340008f0\n" ] } ], @@ -259,9 +258,7 @@ { "data": { "text/plain": [ - "Params([[-0.06611831314621944], [3.1552160317265447], \n", - " [1, 1] = 1.0+0.0im\n", - " [2, 2] = -1.0+0.0im])" + "Params([Float32[0.00041586455], Float32[3.1005328], sparse([1, 2], [1, 2], ComplexF32[1.0f0 + 0.0f0im, -1.0f0 + 0.0f0im], 2, 2)])" ] }, "execution_count": 8, @@ -289,8 +286,8 @@ { "data": { "text/plain": [ - "1-element Array{Float64,1}:\n", - " -0.9977223864977636" + "1-element Vector{Float32}:\n", + " -0.9991572" ] }, "execution_count": 9, @@ -305,15 +302,15 @@ ], "metadata": { "kernelspec": { - "display_name": "Julia 1.5.4", + "display_name": "Julia 1.7.0", "language": "julia", - "name": "julia-1.5" + "name": "julia-1.7" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.5.4" + "version": "1.7.0" } }, "nbformat": 4, diff --git a/examples/training_example2.ipynb b/examples/training_example2.ipynb index 8029969..294a0db 100644 --- a/examples/training_example2.ipynb +++ b/examples/training_example2.ipynb @@ -13,71 +13,9 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[?25l\u001b[2K" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[32m\u001b[1m Updating\u001b[22m\u001b[39m git-repo `https://github.com/Qaintum/Qaintessent.jl`\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[?25h" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[32m\u001b[1m Updating\u001b[22m\u001b[39m registry at `~/.julia/registries/General`\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[?25l\u001b[2K" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "\u001b[32m\u001b[1m Updating\u001b[22m\u001b[39m git-repo `https://github.com/JuliaRegistries/General.git`\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[?25h" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "┌ Warning: Some registries failed to update:\n", - "│ — /home/ga53vuw/.julia/registries/General — failed to fetch from repo\n", - "└ @ Pkg.Types /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.5/Pkg/src/Types.jl:1194\n", - "\u001b[32m\u001b[1m Resolving\u001b[22m\u001b[39m package versions...\n", - "\u001b[32m\u001b[1mNo Changes\u001b[22m\u001b[39m to `/import/home/ga53vuw/Documents/PhD/projects/QAI/Qaintellect.jl/Project.toml`\n", - "\u001b[32m\u001b[1mNo Changes\u001b[22m\u001b[39m to `/import/home/ga53vuw/Documents/PhD/projects/QAI/Qaintellect.jl/Manifest.toml`\n" - ] - } - ], + "outputs": [], "source": [ - "using Pkg; Pkg.add(url=\"https://github.com/Qaintum/Qaintessent.jl\");\n", + "using Qaintessent\n", "using Qaintellect\n", "using LinearAlgebra\n", "using Flux\n", @@ -100,7 +38,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "rg = RotationGate([-0.3770941769323742, -0.18191239085016125, -0.4684997756909257])\n" + "rg = RotationGate(Float32[-0.53703034, 0.05597703, -0.3213241])\n" ] }, { @@ -127,7 +65,7 @@ "N = 4\n", "\n", "ry = RyGate(√2)\n", - "n = randn(Float64, 3)\n", + "n = randn(FloatQ, 3)\n", "n /= norm(n)\n", "rg = RotationGate(0.2π, n)\n", "@show(rg)\n", @@ -153,49 +91,7 @@ { "data": { "text/plain": [ - "Params([[4.71238898038469], [0.3], [-0.3770941769323742, -0.18191239085016125, -0.4684997756909257], \n", - " [1 , 1] = 1.0+0.0im\n", - " [2 , 2] = 1.0+0.0im\n", - " [3 , 3] = 1.0+0.0im\n", - " [4 , 4] = 1.0+0.0im\n", - " [5 , 5] = 1.0+0.0im\n", - " [6 , 6] = 1.0+0.0im\n", - " [7 , 7] = 1.0+0.0im\n", - " [8 , 8] = 1.0+0.0im\n", - " [9 , 9] = 1.0+0.0im\n", - " [10, 10] = 1.0+0.0im\n", - " [11, 11] = 1.0+0.0im\n", - " [12, 12] = 1.0+0.0im\n", - " [13, 13] = 1.0+0.0im\n", - " [14, 14] = 1.0+0.0im\n", - " [15, 15] = 1.0+0.0im\n", - " [16, 16] = 1.0+0.0im, \n", - " [1 , 1] = 0.412232+0.0im\n", - " [2 , 1] = 1.12021-0.256048im\n", - " [3 , 1] = 0.302475+0.717748im\n", - " [4 , 1] = -2.45391-0.991839im\n", - " [5 , 1] = -0.84334+0.657044im\n", - " [6 , 1] = -0.843339+0.632229im\n", - " [7 , 1] = -1.27159+1.11835im\n", - " [8 , 1] = -0.360019-0.698453im\n", - " [9 , 1] = -1.21463-0.462286im\n", - " [10, 1] = 0.246136+0.40925im\n", - " [11, 1] = 0.614472+0.0312881im\n", - " [12, 1] = -0.301658+0.415073im\n", - " ⋮\n", - " [4 , 16] = -0.282751-1.06899im\n", - " [5 , 16] = -1.55817+1.4844im\n", - " [6 , 16] = 0.24081-0.161829im\n", - " [7 , 16] = -0.475453-0.114766im\n", - " [8 , 16] = 0.233323+0.248452im\n", - " [9 , 16] = -0.303145+0.68772im\n", - " [10, 16] = -1.31163-0.0208782im\n", - " [11, 16] = -0.145369-0.0330198im\n", - " [12, 16] = -1.20301-0.620426im\n", - " [13, 16] = 0.446624+1.19501im\n", - " [14, 16] = -1.15907+0.118706im\n", - " [15, 16] = 1.05218-0.523801im\n", - " [16, 16] = 1.56749+0.0im])" + "Params([Float32[4.712389], Float32[0.3], Float32[-0.53703034, 0.05597703, -0.3213241], sparse([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], ComplexF32[1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im, 1.0f0 + 0.0f0im], 16, 16), sparse([1, 2, 3, 4, 5, 6, 7, 8, 9, 10 … 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 … 16, 16, 16, 16, 16, 16, 16, 16, 16, 16], ComplexF32[-1.4366738f0 + 0.0f0im, 0.03560376f0 - 0.6054848f0im, -0.527578f0 - 0.27173388f0im, -1.3991385f0 - 1.1131895f0im, -1.1278617f0 - 0.37390763f0im, 0.75828916f0 - 0.37697834f0im, -0.17399871f0 + 0.68030006f0im, -0.9440648f0 - 0.098141216f0im, 0.24595958f0 + 0.6661913f0im, -0.4319537f0 - 0.27240527f0im … 1.8054765f0 + 0.6945263f0im, 0.7939487f0 - 0.21607582f0im, 0.027468143f0 + 0.08795561f0im, 0.9270779f0 + 0.29685333f0im, -0.1285605f0 - 0.32457453f0im, 0.6224388f0 + 0.89071685f0im, 0.1555624f0 - 0.021069005f0im, -0.5535621f0 + 0.8260739f0im, -0.20685427f0 - 1.1576917f0im, -0.72568375f0 + 0.0f0im], 16, 16)])" ] }, "execution_count": 3, @@ -228,16 +124,18 @@ "name": "stdout", "output_type": "stream", "text": [ - "Initial model evaluation: -0.6411689764188402, target: 0.65\n", - "loss(ψ, e) = 3.2547793683377075\n", - "loss(ψ, e) = 7.703719777548943e-30\n", - "Final model evaluation: 0.6500000000000004, target: 0.65\n" + "Initial model evaluation: -0.5137484192848205, target: 0.65\n", + "loss(ψ, e) = 4.427609752931719\n", + "loss(ψ, e) = 1.1252841773625583e-5\n", + "loss(ψ, e) = 1.1828014123388259e-11\n", + "loss(ψ, e) = 2.1850610211407502e-12\n", + "Final model evaluation: 0.6499985218048095, target: 0.65\n" ] } ], "source": [ "# input quantum state\n", - "ψ = randn(ComplexF64, 2^N)\n", + "ψ = randn(ComplexQ, 2^N)\n", "ψ /= norm(ψ)\n", "\n", "# desired output\n", @@ -268,8 +166,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "ry = RyGate([1.4142135623730951])\n", - "rg = RotationGate([2.2792445765601532, 14.620422188462491, 4.557172204234055])\n" + "ry = RyGate(Float32[1.4142135])\n", + "rg = RotationGate(Float32[2.4036388, -1.0326958, -0.18446656])\n" ] } ], @@ -284,15 +182,15 @@ ], "metadata": { "kernelspec": { - "display_name": "Julia 1.5.3", + "display_name": "Julia 1.7.0", "language": "julia", - "name": "julia-1.5" + "name": "julia-1.7" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.5.3" + "version": "1.7.0" } }, "nbformat": 4, diff --git a/examples/vqt_example.ipynb b/examples/vqt_example.ipynb index 6ee7902..712e114 100644 --- a/examples/vqt_example.ipynb +++ b/examples/vqt_example.ipynb @@ -105,7 +105,7 @@ { "data": { "text/plain": [ - "6×6 BitArray{2}:\n", + "6×6 BitMatrix:\n", " 0 1 1 0 0 0\n", " 1 0 0 1 0 0\n", " 1 0 0 1 1 0\n", @@ -131,7 +131,7 @@ { "data": { "text/plain": [ - "1×6 Array{Int64,2}:\n", + "1×6 Matrix{Int64}:\n", " 2 2 3 3 2 2" ] }, @@ -228,7 +228,7 @@ { "data": { "text/plain": [ - "6×6 BitArray{2}:\n", + "6×6 BitMatrix:\n", " 0 1 0 0 0 0\n", " 1 0 0 0 0 0\n", " 0 0 0 1 0 0\n", @@ -254,7 +254,7 @@ { "data": { "text/plain": [ - "6×6 BitArray{2}:\n", + "6×6 BitMatrix:\n", " 0 0 1 0 0 0\n", " 0 0 0 1 0 0\n", " 1 0 0 0 1 0\n", @@ -430,162 +430,162 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", "\n" ] }, @@ -596,7 +596,7 @@ ], "source": [ "# show eigenvalues\n", - "scatter(eigvals(Matrix(H)), xlabel=L\"i\", ylabel=L\"\\lambda_i\", legend=false)" + "fig = scatter(eigvals(Matrix(H)), xlabel=L\"i\", ylabel=L\"\\lambda_i\", legend=false)" ] }, { @@ -630,7 +630,7 @@ { "data": { "text/plain": [ - "-5.974568533204814" + "-5.974568533204815" ] }, "execution_count": 18, @@ -676,7 +676,7 @@ { "data": { "text/plain": [ - "Array{Float64,2}" + "Matrix{Float64} (alias for Array{Float64, 2})" ] }, "execution_count": 20, @@ -697,7 +697,7 @@ { "data": { "text/plain": [ - "-5.551115123125783e-16" + "-3.3306690738754696e-16" ] }, "execution_count": 21, @@ -721,104 +721,104 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", + "\" transform=\"translate(514, 186)\"/>\n", "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", + "\n", "\n", "\n", - "\n", "\n" ] @@ -1333,7 +1333,7 @@ { "data": { "text/plain": [ - "DensityMatrix([1.0, 0.0, 0.0, 0.38268343236508984, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5000000000000001, 0.0, 0.0, 0.19134171618254497], 2)" + "DensityMatrix(Float32[1.0, 0.0, 0.0, 0.38268343, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.19134171], 2, Float32[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])" ] }, "execution_count": 28, @@ -1417,90 +1417,90 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", "\n" ] @@ -1567,13 +1567,13 @@ { "data": { "text/plain": [ - "6-element Array{Float64,1}:\n", - " 1.868359801242441\n", - " 1.060389067387116\n", - " 0.6242057421026134\n", - " 1.4731764371932827\n", - " 0.8061934487488968\n", - " 0.9868069670558753" + "6-element Vector{Float64}:\n", + " 2.0318529706098656\n", + " 2.717020097618788\n", + " 0.9989301137413403\n", + " 1.827423480478452\n", + " 1.0620257822930346\n", + " 1.703306429578291" ] }, "execution_count": 34, @@ -1594,7 +1594,7 @@ { "data": { "text/plain": [ - "-3.454346355247991" + "-3.4045424285034054" ] }, "execution_count": 35, @@ -1615,7 +1615,7 @@ { "data": { "text/plain": [ - "-8.881784197001252e-16" + "-7.304052225265423e-7" ] }, "execution_count": 36, @@ -1659,7 +1659,7 @@ { "data": { "text/plain": [ - "0.19579532341343417" + "0.1580962285190922" ] }, "execution_count": 38, @@ -1687,7 +1687,7 @@ { "data": { "text/plain": [ - "Params([[-0.032689516897612896, 0.11723480881283915, -0.045725107158529676], [-0.001520505936978918, -0.2860597192812869, -0.14517933263127242], [-0.044905983990877814, 0.13584324485124732, 0.16067012148353474], [0.35345577510743387, 0.1522511129504494, -0.02784330896229452], [0.14938863218235993, -0.10540393806198983, -0.2095642486984505], [0.22021717064502935, -0.036630740017564944, 0.39804581190311705], [-0.10968491520044701], [0.025272938605999738], [-0.23647154235046933], [-0.008800429124181719], [0.13451804982256704], [-0.030642555602742146], [0.014644393047936886], [-0.057949370924255984], [0.1788031093792638], [0.22130813368007962, 0.10181161281624457, 0.349895172414667], [0.05207820405618892, 0.25992990214146633, -0.4411003513588946], [0.17938794853556728, -0.1422455891426142, 0.23752073528613366], [0.1827189357647708, 0.06580117281617619, -0.11518921080548353], [0.1934973944083283, -0.2508076153066435, 0.08224480669615179], [-0.2418979625048874, 0.05148535176720055, -0.13629890988859208], [0.20154963994502484], [-0.26568141081417873], [-0.08761099891259813], [0.1280957061798972], [0.007924579668396676], [-0.25767063818741], [0.06986301428225668, 0.06457884259329327, 0.13931701987728934], [-0.2927576981293754, 0.012127849247136904, 0.04039834409483199], [-0.08067003549566268, 0.05980143027399572, 0.02477438869423316], [-0.21836335540308946, 0.1432329812663253, -0.3286515748333684], [-0.18452433196289325, -0.023517956108989713, -0.02018594625843944], [0.009447246002819414, 0.19800582475438747, 0.20776194351880986], [0.2551887919088065], [0.3901054474244471], [-0.19189338169996753], [-0.16768827766526712], [-0.0017896557300903968], [-0.02683692482320626], [-0.0874508115842101], [0.08844939815918329], [-0.034626460405281355], [1.868359801242441, 1.060389067387116, 0.6242057421026134, 1.4731764371932827, 0.8061934487488968, 0.9868069670558753]])" + "Params([Float32[0.040983554, 0.40255836, 0.052698717], Float32[-0.18232352, -0.090331964, -0.23458481], Float32[-0.05776069, 0.26747993, -0.082058355], Float32[0.20918545, 0.021930521, -0.037663504], Float32[0.07177894, 0.4778533, 0.031728465], Float32[-0.05435562, 0.09969929, 0.12545373], Float32[0.06536225], Float32[0.06538801], Float32[-0.0025789517], Float32[0.07517289], Float32[-0.20450656], Float32[0.15270717], Float32[0.24226269], Float32[0.12700617], Float32[0.1032697], Float32[0.15523788, 0.25014, 0.023242695], Float32[-0.23708455, 0.37828633, 0.06864064], Float32[-0.29249632, -0.1975691, 0.27519658], Float32[0.20765826, 0.12546287, 0.07934507], Float32[0.025782868, -0.016668057, -0.0030892137], Float32[0.019070923, -0.2959702, -0.122801594], Float32[-0.19996083], Float32[0.16453618], Float32[-0.1413626], Float32[0.10085954], Float32[-0.38797143], Float32[-0.42302066], Float32[-0.1435571, -0.06259261, -0.09940565], Float32[0.05932232, 0.14004058, 0.14094594], Float32[-0.12282301, 0.18269998, 0.13822873], Float32[-0.16693018, -0.091183335, -0.024416452], Float32[0.12726356, -0.10762896, -0.11706082], Float32[0.02451601, -0.095727436, -0.07154836], Float32[0.25357822], Float32[0.16726197], Float32[-0.027558237], Float32[0.011515793], Float32[-0.25561082], Float32[-0.07055576], Float32[0.15574162], Float32[0.013619483], Float32[0.26867974], [2.0318529706098656, 2.717020097618788, 0.9989301137413403, 1.827423480478452, 1.0620257822930346, 1.703306429578291]])" ] }, "execution_count": 39, @@ -1714,16 +1714,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "ftarget(θopt): -3.678300721472213, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.13803943670772087\n", - "ftarget(θopt): -4.590431716959359, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.10639718308146373\n", - "ftarget(θopt): -5.01858281019304, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.11718644924475256\n", - "ftarget(θopt): -5.002687717346051, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.12493455726080116\n", - "ftarget(θopt): -5.045669006549844, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.11988221945792962\n", - "ftarget(θopt): -5.05297127716456, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.12645067129811421\n", - "ftarget(θopt): -5.075158770691137, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.1180673811268966\n", - "ftarget(θopt): -5.070433666546223, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.12884618725714092\n", - "ftarget(θopt): -5.074394808644552, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.11874443255684518\n", - "ftarget(θopt): -5.07865488439036, reference: -5.974568533204814; trdistance(θopt, σtherm): 0.11567474448335813\n" + "ftarget(θopt): -3.8078123277395046, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.09304344968001448\n", + "ftarget(θopt): -5.062739362531575, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.09923470591479783\n", + "ftarget(θopt): -5.0783605590405445, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.10650343740452659\n", + "ftarget(θopt): -5.079034989199891, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.10340607401604444\n", + "ftarget(θopt): -5.0661708497557285, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.09890088655326984\n", + "ftarget(θopt): -5.089324888199436, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.09929270270215339\n", + "ftarget(θopt): -5.100506874880439, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.09389422891624996\n", + "ftarget(θopt): -5.088653536256394, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.10653916776205019\n", + "ftarget(θopt): -5.101507146557374, reference: -5.974568533204815; trdistance(θopt, σtherm): 0.105862362889609\n" ] } ], @@ -1749,7 +1748,7 @@ { "data": { "text/plain": [ - "0.11786512992119075" + "0.09954551276510074" ] }, "execution_count": 41, @@ -1770,7 +1769,7 @@ { "data": { "text/plain": [ - "DensityMatrix([1.0, -0.2240240285540103, 0.13888467753134587, 0.23882728585700327, -0.21782546676437542, 0.11825863409919554, -0.04779808642791852, -0.10646227927716767, 0.16857608236370117, -0.07439850585505864 … -0.0005690406193910706, -0.001113420300054632, 0.0010362060028279987, -0.00017741695043474697, 0.0018412725810255813, 0.0003510349081122797, 0.0016678481598943477, -0.0007221969664301109, 0.0003841977188883014, 0.002044061874363257], 6)" + "DensityMatrix(Float32[1.0, -0.2574142, -0.22260246, -0.046752844, -0.27132773, 0.3369535, 0.09101708, -0.030676048, -0.11435073, -0.001410556 … 0.0002822072, -0.00055167964, -0.0011726355, 0.00021294449, 0.0010414027, -0.00018670928, -0.00046235285, 0.00030048873, 0.00029659903, 0.00033298373], 6, Float32[2.2f-44, 0.0, 1.7f-44, 0.0, 2.0f-44, 0.0, 2.1f-44, 0.0, 1.1f-44, 0.0 … -1.0842022f-19, 1.0699999, 0.0, 0.0, -1.0842022f-19, 1.0699999, 0.0, 0.0, -1.0842022f-19, 1.0699999])" ] }, "execution_count": 42, @@ -1794,560 +1793,598 @@ "\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", "\n", - " \n", - " \n", + " \n", + " \n", " \n", "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", + "\n", "\n", + "eUYwAAAAAMozggEAAABQnhEMAAAAgPKMYAAAAACU91819YlKEtjUBwAAAABJRU5ErkJggg==\n", + "\" transform=\"translate(519, 195)\"/>\n", "\n", "\n", - " \n", + " \n", " \n", " \n", "\n", - "\n", + "\n", "\n", "\n", - "\n", "\n" ] @@ -2418,26 +2455,19 @@ "# visualize optimized density matrix\n", "heatmap(log.(max.(real(matrix(ρopt)), 1e-4)), title=L\"\\rho_{\\mathrm{opt}}\", yflip=true, aspect_ratio=:equal)" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Julia 1.5.4", + "display_name": "Julia 1.7.0", "language": "julia", - "name": "julia-1.5" + "name": "julia-1.7" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.5.4" + "version": "1.7.0" } }, "nbformat": 4, diff --git a/src/Qaintellect.jl b/src/Qaintellect.jl index 69d23c4..f970081 100644 --- a/src/Qaintellect.jl +++ b/src/Qaintellect.jl @@ -71,4 +71,7 @@ export export apply +# apply_density +export + apply! end diff --git a/src/flux_integration.jl b/src/flux_integration.jl index 2fa5806..607538e 100644 --- a/src/flux_integration.jl +++ b/src/flux_integration.jl @@ -75,6 +75,20 @@ Zygote.@adjoint apply(ρ::DensityMatrix, moments::Vector{Moment}) = begin end end +# custom adjoint for applying moments to a density matrix +Zygote.@adjoint apply!(ρ::DensityMatrix, moments::Vector{Moment}) = begin + apply!(ρ, moments) + ρ, function(Δ) + if !(Δ isa DensityMatrix) + Δ = DensityMatrix(Δ[1], ρ.N) + end + dmoments, ρbar = Qaintessent.backward_density(moments, ρ, Δ) + collect_gradients(__context__, moments, dmoments) + return (ρbar, dmoments) + end +end + + # custom adjoint for applying a circuit to a density matrix Zygote.@adjoint apply(ρ::DensityMatrix, c::Circuit{N}) where {N} = begin @@ -87,6 +101,17 @@ Zygote.@adjoint apply(ρ::DensityMatrix, c::Circuit{N}) where {N} = begin end end +# custom adjoint for applying a circuit to a density matrix +Zygote.@adjoint apply!(ρ::DensityMatrix, c::Circuit{N}) where {N} = begin + @assert(ρ.N == N) + apply!(ρ, c), function(Δ) + # TODO: don't recompute apply(c, ρ) here + dc, ρbar = Qaintessent.gradients!(c, ρ, Δ) + collect_gradients(__context__, c, dc) + return (ρbar, dc) + end +end + # custom adjoint for DensityMatrix constructor; setting gradient with respect to integer `N` to zero. Zygote.@adjoint DensityMatrix(v::AbstractVector{<:Real}, N::Integer) = DensityMatrix(v, N), ρbar -> (ρbar.v, 0) diff --git a/test/test_gradients.jl b/test/test_gradients.jl index edb1322..4414956 100644 --- a/test/test_gradients.jl +++ b/test/test_gradients.jl @@ -99,11 +99,11 @@ end ρ = density_from_statevector(ψ) grads = Flux.gradient(() -> dot(Δ.v, apply(ρ, c.moments).v), Flux.Params([rz.θ, ps.ϕ, ry.θ, rg.nθ])) - # arguments used implicitly via references f(args...) = dot(Δ.v, apply(ρ, c.moments).v) @test all(isapprox.(ngradient(f, rz.θ, ps.ϕ, ry.θ, rg.nθ), - (grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5)) + (grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5)) + end @@ -118,6 +118,7 @@ end f(args...) = dot(Δ, apply(ρ, c)) @test all(isapprox.(ngradient(f, rz.θ, ps.ϕ, ry.θ, rg.nθ), (grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5)) + end @testset "circuit with measurement gradients for parametric density matrices" begin @@ -131,6 +132,50 @@ end @test all(isapprox.(ngradient(f, θopt, rz.θ, ps.ϕ, ry.θ, rg.nθ), (grads[θopt], grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5)) + end + @testset "moments chain gradients for density matrices" begin + # fictitious gradients of cost function with respect to output density matrix + Δ = DensityMatrix(0.1*randn(Float64, 256), 4) + + ρ = density_from_statevector(ψ) + + grads = Flux.gradient(() -> dot(Δ.v, apply!(deepcopy(ρ), c.moments).v), Flux.Params([rz.θ, ps.ϕ, ry.θ, rg.nθ])) + # arguments used implicitly via references + f(args...) = dot(Δ.v, apply(ρ, c.moments).v) + @test all(isapprox.(ngradient(f, rz.θ, ps.ϕ, ry.θ, rg.nθ), + (grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5)) + end + + @testset "circuit with measurement gradients for density matrices" begin + # fictitious gradients of cost function with respect to circuit output + Δ = [0.3, -1.2] + ρ = density_from_statevector(ψ) + + grads = Flux.gradient(() -> dot(Δ, apply!(deepcopy(ρ), c)), Flux.Params([rz.θ, ps.ϕ, ry.θ, rg.nθ])) + + # arguments used implicitly via references + f(args...) = dot(Δ, apply(ρ, c)) + println() + println(ngradient(f, rz.θ, ps.ϕ, ry.θ, rg.nθ)) + println((grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ])) + @test all(isapprox.(ngradient(f, rz.θ, ps.ϕ, ry.θ, rg.nθ), + (grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5)) + + end + + @testset "circuit with measurement gradients for parametric density matrices" begin + Δ = [0.3, -1.2] + latent_density(θlist) = DensityMatrix(kron([[1-cos(θ), 0, 0, cos(θ)] for θ in θlist]...), length(θlist)) + θopt = π/2 * (1 .+ 0.5*randn(N)) + + grads = Flux.gradient(() -> dot(Δ, apply!(latent_density(θopt), c)), Flux.Params([θopt, rz.θ, ps.ϕ, ry.θ, rg.nθ])) + + f(args...) = dot(Δ, apply(latent_density(θopt), c)) + + @test all(isapprox.(ngradient(f, θopt, rz.θ, ps.ϕ, ry.θ, rg.nθ), + (grads[θopt], grads[rz.θ], grads[ps.ϕ], grads[ry.θ], grads[rg.nθ]), rtol=1e-5, atol=1e-5)) + + end end \ No newline at end of file