{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Resource Estimation of Random Circuit Used in State Vector Simulation\n",
    "\n",
    "This notebook gives the resource estimation of random quantum circuits used for the full state vector simulation in\n",
    "[Simulating 44-Qubit quantum circuits using AWS ParallelCluster](https://aws.amazon.com/blogs/hpc/simulating-44-qubit-quantum-circuits-using-aws-parallelcluster/)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qdk import qsharp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Generating a random circuit\n",
    "\n",
    "Let's now create a random Q# program. Note that the generated circuit will be different on each run, so resource estimates produced for it will vary slightly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "microsoft": {
     "language": "qsharp"
    },
    "vscode": {
     "languageId": "qsharp"
    }
   },
   "outputs": [],
   "source": [
    "%%qsharp\n",
    "import Std.Math.*;\n",
    "import Std.Random.*;\n",
    "\n",
    "operation RunRandomCircuit(nQubits : Int, nGates : Int) : Unit {\n",
    "    use qs = Qubit[nQubits];\n",
    "\n",
    "    for _ in 1 .. nGates {\n",
    "        let rnd = DrawRandomDouble(0., 1.);\n",
    "        if rnd < 0.5 {\n",
    "            // CZ\n",
    "            let controlInd = DrawRandomInt(0, nQubits - 1);\n",
    "            // Make sure target qubit index is distinct from control qubit index\n",
    "            mutable targetInd = DrawRandomInt(0, nQubits - 2);\n",
    "            if targetInd >= controlInd {\n",
    "                set targetInd += 1;\n",
    "            }\n",
    "            CZ(qs[controlInd], qs[targetInd]);\n",
    "        } elif rnd < 0.625 {\n",
    "            // H\n",
    "            let ind = DrawRandomInt(0, nQubits - 1);\n",
    "            H(qs[ind]);\n",
    "        } else {\n",
    "            // R\n",
    "            let ind = DrawRandomInt(0, nQubits - 1);\n",
    "            let gate = [Rx, Ry, Rz][DrawRandomInt(0, 2)];\n",
    "            let angle = DrawRandomDouble(0., PI());\n",
    "            gate(angle, qs[ind]);\n",
    "        }\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Running the Resource Estimator\n",
    "\n",
    "Now we can estimate the resources required for the generated Q# program."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "n_qubits = 43\n",
    "n_gates = 1000\n",
    "qsharp.set_classical_seed(12)\n",
    "result = qsharp.estimate(f\"RunRandomCircuit({n_qubits}, {n_gates})\")\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "jupyter": {
     "outputs_hidden": false,
     "source_hidden": false
    },
    "nteract": {
     "transient": {
      "deleting": false
     }
    }
   },
   "outputs": [],
   "source": [
    "logical_qubits = result['physicalCounts']['breakdown']['algorithmicLogicalQubits']\n",
    "logical_depth = result['physicalCounts']['breakdown']['algorithmicLogicalDepth']\n",
    "# We take the runtime of the circuit from the blog post https://aws.amazon.com/blogs/hpc/simulating-44-qubit-quantum-circuits-using-aws-parallelcluster/, figure 4.\n",
    "target_runtime = 5800\n",
    "target_rqops = logical_qubits * logical_depth / target_runtime\n",
    "\n",
    "print(f\"Logical qubits = {logical_qubits}\")\n",
    "print(f\"Logical depth = {logical_depth}\")\n",
    "print(f\"Target runtime = {target_runtime} seconds\")\n",
    "print(f\"Target rQOPS = {target_rqops}\")\n",
    "\n",
    "print(f\"Execution time on hardware  = {result['physicalCounts']['runtime'] * 1e-9} seconds\")\n",
    "print(f\"rQOPS for execution on hardware = {result['physicalCounts']['rqops']}\")"
   ]
  }
 ],
 "metadata": {
  "kernel_info": {
   "name": "python3"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
