{ "cells": [ { "cell_type": "markdown", "id": "01b3118a", "metadata": {}, "source": [ "# 18 - Hybrid Algorithms & Parameter-Shift Gradients\n", "\n", "Compute quantum gradients using the parameter-shift rule.\n", "\n", "**Concepts:** Parameter-shift rule, analytic gradients, gradient descent" ] }, { "cell_type": "code", "execution_count": null, "id": "7fd8e7f0", "metadata": {}, "outputs": [], "source": [ "import quantsdk as qs\n", "import math\n", "import numpy as np" ] }, { "cell_type": "markdown", "id": "ef3434b7", "metadata": {}, "source": [ "## Parameter-Shift Rule\n", "\n", "For a gate $R(\\theta)$, the gradient is:\n", "\n", "$$\\frac{\\partial \\langle H \\rangle}{\\partial \\theta} = \\frac{1}{2}\\left[\\langle H \\rangle_{\\theta+\\pi/2} - \\langle H \\rangle_{\\theta-\\pi/2}\\right]$$" ] }, { "cell_type": "code", "execution_count": null, "id": "d3a222a7", "metadata": {}, "outputs": [], "source": [ "def parameterized_circuit(theta: float) -> qs.Circuit:\n", " \"\"\"Simple circuit: RY(theta)|0>, measure Z.\"\"\"\n", " circuit = qs.Circuit(1, name=\"param\")\n", " circuit.ry(0, theta)\n", " circuit.measure(0)\n", " return circuit\n", "\n", "def expectation_z(theta: float, shots: int = 4000) -> float:\n", " \"\"\"Measure = P(0) - P(1) = cos(theta).\"\"\"\n", " circuit = parameterized_circuit(theta)\n", " result = qs.run(circuit, shots=shots, seed=42)\n", " p0 = result.counts.get('0', 0) / shots\n", " p1 = result.counts.get('1', 0) / shots\n", " return p0 - p1\n", "\n", "def parameter_shift_gradient(theta: float, shots: int = 4000) -> float:\n", " \"\"\"Compute gradient using parameter-shift rule.\"\"\"\n", " shift = math.pi / 2\n", " forward = expectation_z(theta + shift, shots)\n", " backward = expectation_z(theta - shift, shots)\n", " return (forward - backward) / 2" ] }, { "cell_type": "code", "execution_count": null, "id": "219b8efa", "metadata": {}, "outputs": [], "source": [ "# Compare quantum gradient with exact\n", "print(\"Theta | Quantum Grad | Exact Grad (-sin(theta))\")\n", "print(\"-\" * 52)\n", "for theta in np.linspace(0, 2 * math.pi, 9):\n", " q_grad = parameter_shift_gradient(theta)\n", " exact_grad = -math.sin(theta)\n", " print(f\"{theta:6.3f} | {q_grad:+.4f} | {exact_grad:+.4f}\")" ] }, { "cell_type": "markdown", "id": "5ec30c83", "metadata": {}, "source": [ "## Gradient Descent to Minimize " ] }, { "cell_type": "code", "execution_count": null, "id": "86b4254e", "metadata": {}, "outputs": [], "source": [ "# Minimize = cos(theta) -> minimum at theta = pi\n", "theta = 0.5 # Start near 0\n", "lr = 0.3\n", "history = []\n", "\n", "for step in range(20):\n", " exp_val = expectation_z(theta)\n", " grad = parameter_shift_gradient(theta)\n", " history.append((theta, exp_val))\n", " theta -= lr * grad # Gradient descent\n", "\n", "print(\"Gradient Descent Progress:\")\n", "for i, (t, e) in enumerate(history):\n", " if i % 4 == 0:\n", " bar = '#' * int((e + 1) * 20)\n", " print(f\" Step {i:2d}: theta={t:6.3f}, ={e:+.3f} {bar}\")\n", "\n", "print(f\"\\nFinal theta: {theta:.3f} (optimal: {math.pi:.3f})\")\n", "print(f\"Final : {expectation_z(theta):.3f} (optimal: -1.0)\")" ] }, { "cell_type": "markdown", "id": "d85f50d4", "metadata": {}, "source": [ "## Multi-Parameter Gradient" ] }, { "cell_type": "code", "execution_count": null, "id": "0c45d950", "metadata": {}, "outputs": [], "source": [ "def two_param_circuit(t0: float, t1: float) -> float:\n", " \"\"\"Circuit with two RY gates, measure .\"\"\"\n", " circuit = qs.Circuit(2, name=\"2param\")\n", " circuit.ry(0, t0).ry(1, t1).cx(0, 1).measure(0)\n", " result = qs.run(circuit, shots=4000, seed=42)\n", " p0 = result.counts.get('0', 0) / 4000\n", " p1 = result.counts.get('1', 0) / 4000\n", " return p0 - p1\n", "\n", "# Gradient with respect to t0\n", "t0, t1 = 1.0, 0.5\n", "shift = math.pi / 2\n", "\n", "grad_t0 = (two_param_circuit(t0 + shift, t1) - two_param_circuit(t0 - shift, t1)) / 2\n", "grad_t1 = (two_param_circuit(t0, t1 + shift) - two_param_circuit(t0, t1 - shift)) / 2\n", "\n", "print(f\"Parameters: t0={t0:.2f}, t1={t1:.2f}\")\n", "print(f\"Gradient: (d/dt0={grad_t0:+.4f}, d/dt1={grad_t1:+.4f})\")" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }