From c9501e8c642b7e2bf412abb344e2c96e32d62cf2 Mon Sep 17 00:00:00 2001 From: Iskandar Sitdikov Date: Mon, 9 Jan 2023 11:13:05 -0500 Subject: [PATCH] Docs: update electronic structure problem with program interface --- docs/tutorials/01_quantum_serverless.ipynb | 109 +++++++++++++- .../06_electronic_structure_problem.ipynb | 137 +++++------------- .../electronic_structure_problem.py | 87 ++++++++--- 3 files changed, 200 insertions(+), 133 deletions(-) diff --git a/docs/tutorials/01_quantum_serverless.ipynb b/docs/tutorials/01_quantum_serverless.ipynb index 52a3725f9..c1b8f1ce5 100644 --- a/docs/tutorials/01_quantum_serverless.ipynb +++ b/docs/tutorials/01_quantum_serverless.ipynb @@ -13,9 +13,7 @@ "- building blocks of distributed computation\n", "- resource allocation and execution management\n", "- assembling all together\n", - "- electronic structure problem example\n", - "- infrastructure\n", - "- links and references" + "- running as async program" ] }, { @@ -195,13 +193,13 @@ "serverless = QuantumServerless({\"providers\": [...]})\n", "serverless = QuantumServerless.load_configuration(\"\")\n", "print(serverless)\n", - "# \n", + "# \n", "\n", "with serverless.provider(\"local\"):\n", " exp_val_execution_reference = exp_val_remote(circuit, obs)\n", " collected_exp_value = quantum_serverless.get(exp_val_execution_reference)\n", "\n", - "with serverless.provider(\"ibm\"):\n", + "with serverless.provider(\"ibm-cloud\"):\n", " exp_val_execution_reference = exp_val_remote(circuit, obs)\n", " collected_exp_value = quantum_serverless.get(exp_val_execution_reference)\n", "```" @@ -214,12 +212,14 @@ "source": [ "## Assembling all together\n", "\n", - "Now we have all the important concepts in place and we can assemble our first simple example of a distributed program." + "Now we have all the important concepts in place and we can assemble our first simple example of a distributed program.\n", + "\n", + "> NOTE: make sure to run docker-compose to use this example" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "id": "6277cbd3-a1ac-4a8f-8a29-c9c92732e780", "metadata": {}, "outputs": [ @@ -227,7 +227,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "[EstimatorResult(values=array([1.]), metadata=[{}]), EstimatorResult(values=array([1.]), metadata=[{}]), EstimatorResult(values=array([-0.8821732]), metadata=[{}])]\n" + "[EstimatorResult(values=array([1.]), metadata=[{}]), EstimatorResult(values=array([1.]), metadata=[{}]), EstimatorResult(values=array([1.]), metadata=[{}])]\n" ] } ], @@ -257,6 +257,99 @@ " \n", "print(collected_exp_values)" ] + }, + { + "cell_type": "markdown", + "id": "a962b872-427d-47c6-9eea-56a53bdfcdc6", + "metadata": {}, + "source": [ + "## Running as async program\n", + "\n", + "In most of the cases we want to run our scripts as sync programs, so we can lunch them and forget, then later on check results.\n", + "In order to do so we will use `Program` interface.\n", + "\n", + "Let's reuse benchmark script which covers all the concepts covered above and which you can find [here](./source_files/benchmark.py)." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "75efe890-d7ea-4747-973c-b90e4df9fe39", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-01-09 10:42:24,138\tINFO dashboard_sdk.py:362 -- Package gcs://_ray_pkg_521b4aa7701fdb06.zip already exists, skipping upload.\n" + ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from quantum_serverless import Program\n", + "\n", + "program = Program(\n", + " name=\"brnchmark_program\",\n", + " entrypoint=\"benchmark.py\",\n", + " working_dir=\"./source_files/\",\n", + " description=\"Benchmark program\"\n", + ")\n", + "\n", + "job = serverless.run_program(program)\n", + "job" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "0a7c52b4-c51e-4497-a013-5b1fdc9a5a79", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "job.status()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f650750b-4b39-4932-b9dc-a51171d1d146", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Execution time: 10.197080135345459\\nResults: [[EstimatorResult(values=array([-1.57009246e-16+6.35678836e-17j, 0.00000000e+00+2.00000000e+00j,\\n 1.00000000e+00+4.89879098e-01j, 0.00000000e+00-5.93914329e-01j,\\n 1.00000000e+00+3.84977936e-17j, -3.02888967e-01+0.00000000e+00j,\\n 9.23868961e-01+8.41944092e-01j, -1.00000000e+00-6.98797220e-17j,\\n 9.91094361e-01+5.68284953e-01j, -4.16333634e-17-1.00000000e+00j,\\n 8.07303767e-01+0.00000000e+00j, -5.34510053e-17+0.00000000e+00j,\\n -3.34083829e-01+1.00000000e+00j, 0.00000000e+00+1.65570683e+00j,\\n 8.87382321e-01+0.00000000e+00j, -8.81812854e-01-1.22464680e-16j,\\n -3.08751328e-01-5.78644041e-18j, 0.00000000e+00+1.92837761e-16j,\\n 0.00000000e+00+1.00000000e+00j, 2.00000000e+00+2.58341370e-16j,\\n -1.40395784e-16-8.97966034e-18j, 0.00000000e+00-8.65956056e-17j,\\n -1.22464680e-16-8.72832410e-34j, 1.00000000e+00+0.00000000e+00j,\\n 3.97958431e-01+6.42319385e-01j, -1.00000000e+00+1.00000000e+00j,\\n -1.66533454e-16+9.75159526e-01j, 0.00000000e+00+0.00000000e+00j,\\n -1.00000000e+00-4.83503087e-01j, -9.52623642e-01-5.95841695e-02j]), metadata=[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]), EstimatorResult(values=array([-1.57009246e-16+6.35678836e-17j, 0.00000000e+00+2.00000000e+00j,\\n 1.00000000e+00+4.89879098e-01j, 0.00000000e+00-5.93914329e-01j,\\n 1.00000000e+00+3.84977936e-17j, -3.02888967e-01+0.00000000e+00j,\\n 9.23868961e-01+8.41944092e-01j, -1.00000000e+00-6.98797220e-17j,\\n 9.91094361e-01+5.68284953e-01j, -4.16333634e-17-1.00000000e+00j,\\n 8.07303767e-01+0.00000000e+00j, -5.34510053e-17+0.00000000e+00j,\\n -3.34083829e-01+1.00000000e+00j, 0.00000000e+00+1.65570683e+00j,\\n 8.87382321e-01+0.00000000e+00j, -8.81812854e-01-1.22464680e-16j,\\n -3.08751328e-01-5.78644041e-18j, 0.00000000e+00+1.92837761e-16j,\\n 0.00000000e+00+1.00000000e+00j, 2.00000000e+00+2.58341370e-16j,\\n -1.40395784e-16-8.97966034e-18j, 0.00000000e+00-8.65956056e-17j,\\n -1.22464680e-16-8.72832410e-34j, 1.00000000e+00+0.00000000e+00j,\\n 3.97958431e-01+6.42319385e-01j, -1.00000000e+00+1.00000000e+00j,\\n -1.66533454e-16+9.75159526e-01j, 0.00000000e+00+0.00000000e+00j,\\n -1.00000000e+00-4.83503087e-01j, -9.52623642e-01-5.95841695e-02j]), metadata=[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]), EstimatorResult(values=array([-1.57009246e-16+6.35678836e-17j, 0.00000000e+00+2.00000000e+00j,\\n 1.00000000e+00+4.89879098e-01j, 0.00000000e+00-5.93914329e-01j,\\n 1.00000000e+00+3.84977936e-17j, -3.02888967e-01+0.00000000e+00j,\\n 9.23868961e-01+8.41944092e-01j, -1.00000000e+00-6.98797220e-17j,\\n 9.91094361e-01+5.68284953e-01j, -4.16333634e-17-1.00000000e+00j,\\n 8.07303767e-01+0.00000000e+00j, -5.34510053e-17+0.00000000e+00j,\\n -3.34083829e-01+1.00000000e+00j, 0.00000000e+00+1.65570683e+00j,\\n 8.87382321e-01+0.00000000e+00j, -8.81812854e-01-1.22464680e-16j,\\n -3.08751328e-01-5.78644041e-18j, 0.00000000e+00+1.92837761e-16j,\\n 0.00000000e+00+1.00000000e+00j, 2.00000000e+00+2.58341370e-16j,\\n -1.40395784e-16-8.97966034e-18j, 0.00000000e+00-8.65956056e-17j,\\n -1.22464680e-16-8.72832410e-34j, 1.00000000e+00+0.00000000e+00j,\\n 3.97958431e-01+6.42319385e-01j, -1.00000000e+00+1.00000000e+00j,\\n -1.66533454e-16+9.75159526e-01j, 0.00000000e+00+0.00000000e+00j,\\n -1.00000000e+00-4.83503087e-01j, -9.52623642e-01-5.95841695e-02j]), metadata=[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}])]]\\n/home/ray/anaconda3/lib/python3.7/site-packages/ray/_private/worker.py:983: UserWarning: len(ctx) is deprecated. Use len(ctx.address_info) instead.\\n warnings.warn(\"len(ctx) is deprecated. Use len(ctx.address_info) instead.\")\\n'" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "job.logs()" + ] } ], "metadata": { diff --git a/docs/tutorials/06_electronic_structure_problem.ipynb b/docs/tutorials/06_electronic_structure_problem.ipynb index 2999ec868..beef729c4 100644 --- a/docs/tutorials/06_electronic_structure_problem.ipynb +++ b/docs/tutorials/06_electronic_structure_problem.ipynb @@ -93,139 +93,72 @@ }, { "cell_type": "code", - "execution_count": 1, - "id": "da57cdda-1b29-4029-898d-f752e8788eca", + "execution_count": 9, + "id": "290bf01e-3175-4c60-b7b7-ce02ea40fb08", "metadata": {}, "outputs": [], "source": [ - "import os\n", - "import matplotlib.pyplot as plt\n", - "\n", - "from qiskit_ibm_runtime import QiskitRuntimeService\n", - "from qiskit_nature.drivers import Molecule\n", - "from qiskit.algorithms.optimizers import SPSA\n", - "\n", "from quantum_serverless import QuantumServerless, Program" ] }, { "cell_type": "code", - "execution_count": 2, - "id": "2533f860-a40c-47bb-a067-cdb19f1c6c51", - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "sys.path.append(\"./source_files/\")\n", - "\n", - "from source_files.electronic_structure_problem import electronic_structure_problem" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "47a01b11-6aa2-44c6-a8a1-1e42600dce92", - "metadata": {}, - "outputs": [], - "source": [ - "# default initialization\n", - "serverless = QuantumServerless()" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "3a989e04-cecb-485a-93b1-b4dcaacb1539", - "metadata": {}, - "outputs": [], - "source": [ - "USE_RUNTIME = False\n", - "\n", - "service = None\n", - "backends = None\n", - "if USE_RUNTIME:\n", - " service = QiskitRuntimeService()\n", - " names = [\"ibmq_qasm_simulator\", \"ibmq_qasm_simulator\", \"ibmq_qasm_simulator\"]\n", - " backends = [service.backend(name) for name in names]" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "24a75e07-2074-41fb-8e80-b15da91fed6d", + "execution_count": 36, + "id": "c35bf9df-e68c-45b7-a992-2471aee29d60", "metadata": {}, "outputs": [], "source": [ - "%%capture\n", - "\n", - "with serverless:\n", - " energies = electronic_structure_problem(\n", - " molecules=[\n", - " Molecule(geometry=[(\"H\", [0.0, 0.0, 0.0]), (\"Li\", [0.0, 0.0, 1.0])], charge=0, multiplicity=1),\n", - " Molecule(geometry=[(\"H\", [0.0, 0.0, 0.0]), (\"Li\", [0.0, 0.0, 1.5])], charge=0, multiplicity=1),\n", - " Molecule(geometry=[(\"H\", [0.0, 0.0, 0.0]), (\"Li\", [0.0, 0.0, 2.0])], charge=0, multiplicity=1),\n", - " ],\n", - " initial_points=[\n", - " [0.1, 0.1, 0.1, 0.1],\n", - " [0.01, 0.01, 0.01, 0.01],\n", - " [0.001, 0.001, 0.001, 0.001],\n", - " ],\n", - " service=service,\n", - " backends=backends,\n", - " optimization_level = 1,\n", - " resilience_level = 1,\n", - " shots=4000,\n", - " optimizer=SPSA(),\n", - " use_local_simulator=not USE_RUNTIME\n", - " )" + "serverless = QuantumServerless.load_configuration(\"./serverless_config.json\") # config with docker setup" ] }, { "cell_type": "code", - "execution_count": 6, - "id": "d2a86d99-26e0-4806-9a91-1156e80c6505", + "execution_count": 41, + "id": "a0789a71-0b84-4736-9f34-579205dbc3c2", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Energies: [-0.984816780849255, -1.0949470017011422, -0.7100079453821824]\n", - "Shifts: [-6.6097847711303315, -6.781951626949086, -6.87041467842551]\n", - "Energy + shift: [-7.594601551979586, -7.876898628650228, -7.580422623807692]\n" - ] + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" } ], "source": [ - "print(\"Energies: \", [e[0] for e in energies])\n", - "print(\"Shifts: \", [e[1] for e in energies])\n", - "print(\"Energy + shift: \", [e[0] + e[1] for e in energies])" + "program = Program(\n", + " name=\"electronic_structure\",\n", + " entrypoint=\"electronic_structure_problem.py\",\n", + " working_dir=\"./source_files/\",\n", + " description=\"Electronic structure program\",\n", + " dependencies=[\"pyscf==1.6.3\"]\n", + ")\n", + "\n", + "job = serverless.run_program(program)\n", + "job" ] }, { "cell_type": "code", - "execution_count": 7, - "id": "c3d189e7-0e37-4e3c-bcd5-21a3f8c53b85", + "execution_count": null, + "id": "0d0c3e32-ea08-4939-a4ca-6b6150f2c2c8", "metadata": {}, "outputs": [ { - "data": { - "image/png": "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9TZnKS4uTvv27auTsJSUlKQJEyaYtgkPD3dYT01NVWBgoOLj453+nI8++ki5ublau3btTdv27t1bXl5e+vzzz2sMSz4+PvLx8XH68wEAgPuqdVgaMWKE5s+fr6NHj6pbt27y8vJy2F+bEBMUFKSgoCCn2xuGodTUVCUkJFT5XDMpKSm677771KNHj5u2PXLkiMrLyxUaGur08QEAQNN1Wy+lrHKwen4p5bZt2xQTE6OjR48qMjKyyv6IiAgtWbJEY8aMsW8rLi5WaGioXnzxRc2YMcOh/YkTJ7RmzRoNHz5cQUFBOnr0qObOnavmzZsrJydHHh4eTtXFqwMAAHA/9fYY7vuvCmhIKSkpio6OrjYoSVJubq5sNpvDtoyMDBmGoYkTJ1Zp7+3trW3btmn58uUqKSlRWFiYRowYoeTkZKeDEgAAaNrc4qWUjR0jSwAAuB9n799O/5Du8OHDHUZtnn/+eX333Xf29XPnzikqKurWqgUAAGiknA5LH3zwgcPX5X//+987/ATJ1atXlZubW7fVAQAAuJjTYen7T+t4egcAAH4InA5LAAAAP0ROhyWLxVLlR2vNfsQWAACgKXD61QGGYWjKlCn2N1dfuXJFM2bMkJ+fnyQ5zGcCAABoKpwOS48//rjD+uTJk6u0SUhIuP2KAAAAGhGnw1Jqamp91gEAANAoMcEbAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADABGEJAADAhFuEpezsbFkslmqXnJycGvuVlJQoKSlJHTp0UPPmzRUZGamVK1c6tCktLdWsWbMUFBQkPz8/xcfHKz8/v75PCQAAuAm3CEvR0dEqKChwWKZNm6bw8HD16dOnxn5z5szRpk2btHr1ah07dkxz5szRrFmz9P7779vbPP3008rMzFRGRoZ27dqlkpISPfLII6qoqGiIUwMAAI2cW4Qlb29vhYSE2JfAwEBlZWVp6tSpslgsNfbbvXu3Hn/8cT300EMKDw/X9OnT1aNHD+3bt0+SZLPZlJKSohdffFExMTHq1auXVq9erc8++0xbt25tqNMDAACNmFuEpe/LysrS2bNnNWXKFNN2AwcOVFZWlk6fPi3DMLRjxw4dP35ccXFxkqT9+/ervLxcsbGx9j7t2rVT165d9cknn9R43NLSUhUXFzssAACgaXLLsJSSkqK4uDiFhYWZtluxYoWioqLUoUMHeXt7a9iwYfrTn/6kgQMHSpIKCwvl7e2tO+64w6Ff27ZtVVhYWONxlyxZIqvVal9uVgcAAHBfLg1LixYtqnHi9vXl+iOz6/Lz8/XBBx8oMTHxpsdfsWKF9uzZo6ysLO3fv18vvviiZs6cedNHbIZhmD7eW7BggWw2m305deqUcycMAADcjqcrPzwpKUkTJkwwbRMeHu6wnpqaqsDAQMXHx5v2u3z5sp599lllZmZqxIgRkqTu3bvr0KFD+uMf/6iYmBiFhISorKxM3377rcPoUlFRkaKjo2s8to+Pj3x8fG5ydgAAoClwaVgKCgpSUFCQ0+0Nw1BqaqoSEhLk5eVl2ra8vFzl5eVq1sxx8MzDw0OVlZWSpPvuu09eXl7asmWLxo0bJ0kqKCjQ4cOHtXTp0lqeDQAAaIrcas7S9u3blZeXV+MjuIiICGVmZkqSAgICNGjQIM2fP1/Z2dnKy8tTWlqa3njjDY0ZM0aSZLValZiYqLlz52rbtm06ePCgJk+erG7duikmJqbBzgsAADReLh1Zqq2UlBRFR0crMjKy2v25ubmy2Wz29YyMDC1YsECTJk3S+fPn1bFjRz3//POaMWOGvc2yZcvk6empcePG6fLlyxoyZIjS0tLk4eFR7+cDAAAaP4thGIari3B3xcXFslqtstlsCggIcHU5AADACc7ev93qMRwAAEBDIywBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYICwBAACYcIuwlJ2dLYvFUu2Sk5NTY7+SkhIlJSWpQ4cOat68uSIjI7Vy5UqHNg899FCVY06YMKG+TwkAALgJT1cX4Izo6GgVFBQ4bFu4cKG2bt2qPn361Nhvzpw52rFjh1avXq3w8HBt3rxZM2fOVLt27TRq1Ch7uyeeeELPPfecfb158+Z1fxIAAMAtuUVY8vb2VkhIiH29vLxcWVlZSkpKksViqbHf7t279fjjj+uhhx6SJE2fPl1//vOftW/fPoew1KJFC4fj30xpaalKS0vt68XFxbU4GwAA4E7c4jHc92VlZens2bOaMmWKabuBAwcqKytLp0+flmEY2rFjh44fP664uDiHdmvWrFFQUJDuvfdezZs3TxcuXDA97pIlS2S1Wu1LWFjY7Z4SAABopCyGYRiuLqK2hg8fLknauHGjabuysjI98cQTeuONN+Tp6almzZrptdde03/+53/a27z66qvq1KmTQkJCdPjwYS1YsEB33XWXtmzZUuNxqxtZCgsLk81mU0BAwG2eHQAAaAjFxcWyWq03vX+79DHcokWLtHjxYtM2OTk5DvOS8vPz9cEHH+jtt9++6fFXrFihPXv2KCsrSx07dtSHH36omTNnKjQ0VDExMZKuzVe6rmvXrrr77rvVp08fHThwQL179672uD4+PvLx8XHmFAEAgJtz6cjS2bNndfbsWdM24eHh8vX1ta//13/9l1566SWdPn1aXl5eNfa7fPmyrFarMjMzNWLECPv2adOmKT8/X5s2baq2n2EY8vHx0Ztvvqnx48c7dR7OJlMAANB4uMXIUlBQkIKCgpxubxiGUlNTlZCQYBqUpGuTwMvLy9WsmeO0LA8PD1VWVtbY78iRIyovL1doaKjTdQEAgKbLrSZ4b9++XXl5eUpMTKx2f0REhDIzMyVJAQEBGjRokObPn6/s7Gzl5eUpLS1Nb7zxhsaMGSNJOnHihJ577jnt27dPX331lTZu3KjHHntMvXr10oABAxrsvAAAQOPlFq8OuC4lJUXR0dGKjIysdn9ubq5sNpt9PSMjQwsWLNCkSZN0/vx5dezYUc8//7xmzJgh6dorCbZt26bly5erpKREYWFhGjFihJKTk+Xh4dEg5wQAABo3t/w2XGPDnCUAANyPs/dvt3oMBwAA0NAISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACYISwAAACY8XV0AADRWFZWG9uadV9GFKwr291XfTq3l0czi6rIANDDCEgBUY9PhAi1ef1QFtiv2baFWXyWPjNKwrqEurAxAQ+MxHAB8z6bDBfrZ6gMOQUmSCm1X9LPVB7TpcIGLKgPgCoQlALhBRaWhxeuPyqhm3/Vti9cfVUVldS0ANEWEJQC4wd6881VGlG5kSCqwXdHevPMNVxQAlyIsAcANii7UHJRupR0A90dYAoAbBPv71mk7AO6PsAQAN+jbqbVCrb6q6QUBFl37VlzfTq0bsiwALkRYAoAbeDSzKHlklCRVCUzX15NHRvG+JeAHhLAEAN8zrGuoVk7urRCr46O2EKuvVk7uzXuWgB8YXkoJANUY1jVUQ6NCeIM3AMISANTEo5lF/TsHuroMAC7GYzgAAAAThCUAAAAThCUAAAAThCUAAAAThCUAAAAThCUAAAAThCUAAAAThCUAAAAThCUAAAATvMG7DhiGIUkqLi52cSUAAMBZ1+/b1+/jNSEs1YELFy5IksLCwlxcCQAAqK0LFy7IarXWuN9i3CxO4aYqKyt15swZ+fv7y2Kpux/ZLC4uVlhYmE6dOqWAgIA6Oy6q4lo3DK5zw+A6Nwyuc8Ooz+tsGIYuXLigdu3aqVmzmmcmMbJUB5o1a6YOHTrU2/EDAgL4H7GBcK0bBte5YXCdGwbXuWHU13U2G1G6jgneAAAAJghLAAAAJghLjZiPj4+Sk5Pl4+Pj6lKaPK51w+A6Nwyuc8PgOjeMxnCdmeANAABggpElAAAAE4QlAAAAE4QlAAAAE4QlAAAAE4QlF/rwww81cuRItWvXThaLRe+9995N++zcuVP33XeffH19deedd+qVV16p/0LdXG2v87vvvquhQ4eqTZs2CggIUP/+/fXBBx80TLFu7Fb+PF/38ccfy9PTUz179qy3+pqKW7nOpaWl+tWvfqWOHTvKx8dHnTt31qpVq+q/WDd3K9d6zZo16tGjh1q0aKHQ0FD99Kc/1blz5+q/WDe1ZMkS3X///fL391dwcLBGjx6t3Nzcm/Zr6HshYcmFLl68qB49eujll192qn1eXp6GDx+uBx54QAcPHtSzzz6r2bNn65133qnnSt1bba/zhx9+qKFDh2rjxo3av3+/Bg8erJEjR+rgwYP1XKl7q+11vs5msykhIUFDhgypp8qallu5zuPGjdO2bduUkpKi3NxcpaenKyIioh6rbBpqe6137dqlhIQEJSYm6siRI1q3bp1ycnI0bdq0eq7Ufe3cuVM///nPtWfPHm3ZskVXr15VbGysLl68WGMfl9wLDTQKkozMzEzTNr/4xS+MiIgIh21PPvmk0a9fv3qsrGlx5jpXJyoqyli8eHHdF9RE1eY6jx8/3vj1r39tJCcnGz169KjXupoaZ67z3//+d8NqtRrnzp1rmKKaKGeu9R/+8AfjzjvvdNi2YsUKo0OHDvVYWdNSVFRkSDJ27txZYxtX3AsZWXIju3fvVmxsrMO2uLg47du3T+Xl5S6qqumrrKzUhQsX1Lp1a1eX0uSkpqbqxIkTSk5OdnUpTVZWVpb69OmjpUuXqn379urSpYvmzZuny5cvu7q0Jic6Olr5+fnauHGjDMPQN998o7/+9a8aMWKEq0tzGzabTZJM/751xb2QH9J1I4WFhWrbtq3DtrZt2+rq1as6e/asQkNDXVRZ0/biiy/q4sWLGjdunKtLaVI+//xz/fKXv9RHH30kT0/+KqovX375pXbt2iVfX19lZmbq7Nmzmjlzps6fP8+8pToWHR2tNWvWaPz48bpy5YquXr2q+Ph4vfTSS64uzS0YhqFnnnlGAwcOVNeuXWts54p7ISNLbsZisTisG//3Avbvb0fdSE9P16JFi7R27VoFBwe7upwmo6KiQj/5yU+0ePFidenSxdXlNGmVlZWyWCxas2aN+vbtq+HDh+u///u/lZaWxuhSHTt69Khmz56t3/zmN9q/f782bdqkvLw8zZgxw9WluYWkpCT94x//UHp6+k3bNvS9kH/OuZGQkBAVFhY6bCsqKpKnp6cCAwNdVFXTtXbtWiUmJmrdunWKiYlxdTlNyoULF7Rv3z4dPHhQSUlJkq7d1A3DkKenpzZv3qyHH37YxVU2DaGhoWrfvr2sVqt9W2RkpAzDUH5+vu6++24XVte0LFmyRAMGDND8+fMlSd27d5efn58eeOAB/fa3v2X038SsWbOUlZWlDz/8UB06dDBt64p7IWHJjfTv31/r16932LZ582b16dNHXl5eLqqqaUpPT9fUqVOVnp7OfIN6EBAQoM8++8xh25/+9Cdt375df/3rX9WpUycXVdb0DBgwQOvWrVNJSYlatmwpSTp+/LiaNWt205sSaufSpUtVHil7eHhI+vfIBxwZhqFZs2YpMzNT2dnZTv2/74p7IY/hXKikpESHDh3SoUOHJF37OuShQ4f09ddfS5IWLFighIQEe/sZM2bo5MmTeuaZZ3Ts2DGtWrVKKSkpmjdvnivKdxu1vc7p6elKSEjQiy++qH79+qmwsFCFhYX2iYeoXm2uc7NmzdS1a1eHJTg4WL6+vuratav8/PxcdRqNXm3/PP/kJz9RYGCgfvrTn+ro0aP68MMPNX/+fE2dOlXNmzd3xSm4jdpe65EjR+rdd9/VypUr9eWXX+rjjz/W7Nmz1bdvX7Vr184Vp9Do/fznP9fq1av11ltvyd/f3/737Y2PiBvFvbDevmeHm9qxY4chqcry+OOPG4ZhGI8//rgxaNAghz7Z2dlGr169DG9vbyM8PNxYuXJlwxfuZmp7nQcNGmTaHtW7lT/PN+LVAc65let87NgxIyYmxmjevLnRoUMH45lnnjEuXbrU8MW7mVu51itWrDCioqKM5s2bG6GhocakSZOM/Pz8hi/eTVR3fSUZqamp9jaN4V5o+b9iAQAAUA0ewwEAAJggLAEAAJggLAEAAJggLAEAAJggLAEAAJggLAEAAJggLAEAAJggLAEAAJggLAFwKxaLRe+99169HDstLU2tWrWyry9atEg9e/as888pKyvTXXfdpY8//rhW/ebNm6fZs2fXeT0AzBGWADQqU6ZM0ejRo2vcX1BQoB//+Mf29ZrC082O44x58+Zp27ZtTrWtTbD6y1/+oo4dO2rAgAFV9k2fPl0eHh7KyMiosu8Xv/iFUlNTlZeX59TnAKgbhCUAbiUkJEQ+Pj4N8lktW7ZUYGBgnR/3pZde0rRp06psv3TpktauXav58+crJSWlyv7g4GDFxsbqlVdeqfOaANSMsATArdTlY7i0tDT96Ec/UosWLTRmzBidO3fOYf/3R4uys7PVt29f+fn5qVWrVhowYIBOnjyptLQ0LV68WJ9++qksFossFovS0tKq/cwDBw7oiy++0IgRI6rsW7dunaKiorRgwQJ9/PHH+uqrr6q0iY+PV3p6+u2cNoBaIiwB+EH63//9X02dOlUzZ87UoUOHNHjwYP32t7+tsf3Vq1c1evRoDRo0SP/4xz+0e/duTZ8+XRaLRePHj9fcuXN17733qqCgQAUFBRo/fny1x/nwww/VpUsXBQQEVNmXkpKiyZMny2q1avjw4UpNTa3Spm/fvjp16pROnjx56ycPoFY8XV0AANyuiRMnysPDw2FbaWlptaM31y1fvlxxcXH65S9/KUnq0qWLPvnkE23atKna9sXFxbLZbHrkkUfUuXNnSVJkZKR9f8uWLeXp6amQkBDTWr/66iu1a9euyvbPP/9ce/bs0bvvvitJmjx5smbPnq3k5GQ1a/bvf9e2b9/efpyOHTuafhaAusHIEgC3t2zZMh06dMhhiY+PN+1z7Ngx9e/f32Hb99dv1Lp1a02ZMkVxcXEaOXKkli9froKCglrXevnyZfn6+lbZnpKSori4OAUFBUmShg8frosXL2rr1q0O7Zo3by7p2vwmAA2DsATA7YWEhOiuu+5yWPz9/U37GIZR689JTU3V7t27FR0drbVr16pLly7as2dPrY4RFBSkb7/91mFbRUWF3njjDW3YsEGenp7y9PRUixYtdP78+SoTvc+fPy9JatOmTa3rB3BreAwH4AcpKiqqStBxJvj06tVLvXr10oIFC9S/f3+99dZb6tevn7y9vVVRUeFU/5UrV8owDFksFknSxo0bdeHCBR08eNDhceI///lPTZo0SefOnbN/K+/w4cPy8vLSvffeW5vTBXAbCEsAGh2bzaZDhw45bGvdurV+9KMf1dlnzJ49W9HR0Vq6dKlGjx6tzZs31zhfSZLy8vL0l7/8RfHx8WrXrp1yc3N1/PhxJSQkSJLCw8OVl5enQ4cOqUOHDvL396/2FQeDBw/WxYsXdeTIEXXt2lXStUdwI0aMUI8ePRza3nvvvXr66ae1evVqPfXUU5Kkjz76SA888ID9cRyA+sdjOACNTnZ2tn0E5/rym9/8pk4/o1+/fnrttdf00ksvqWfPntq8ebN+/etf19i+RYsW+uc//6lHH31UXbp00fTp05WUlKQnn3xSkvToo49q2LBhGjx4sNq0aVPj1/sDAwM1duxYrVmzRpL0zTffaMOGDXr00UertLVYLBo7dqzDo7j09HQ98cQTt3PqAGrJYtzKg3sAwC377LPPFBMToy+++OKmc6tutGHDBs2fP1//+Mc/5OnJgwGgoTCyBAANrFu3blq6dGm1L500c/HiRaWmphKUgAbGyBIAAIAJRpYAAABMEJYAAABMEJYAAABMEJYAAABMEJYAAABMEJYAAABMEJYAAABMEJYAAABMEJYAAABM/H+7cM3yUj1newAAAABJRU5ErkJggg==\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" + "name": "stdout", + "output_type": "stream", + "text": [ + "Energies: [-0.9848168378887934, -0.9094747516508735, -0.9811709328709944]\n", + "Shifts: [-6.609784771130337, -6.781951626949085, -6.870414678425508]\n", + "Energy + shift: [-7.59460160901913, -7.691426378599958, -7.851585611296502]\n" + ] } ], "source": [ - "dist = [1.0,1.5,2.0]\n", - "plt.plot(dist, [e[0] + e[1] for e in energies], 'o', label = 'VQE')\n", - "plt.xlabel('LiH dist (A)')\n", - "plt.ylabel('Enrgy (Ha)')\n", - "plt.legend()\n", - "plt.show()" + "print(\"\\n\".join(job.logs().split(\"\\n\")[-4:-1]))" ] } ], diff --git a/docs/tutorials/source_files/electronic_structure_problem.py b/docs/tutorials/source_files/electronic_structure_problem.py index 577247682..c2646fe08 100644 --- a/docs/tutorials/source_files/electronic_structure_problem.py +++ b/docs/tutorials/source_files/electronic_structure_problem.py @@ -28,15 +28,15 @@ @run_qiskit_remote(target={"cpu": 2}) def ground_state_solve( - molecule: Molecule, - initial_point: Union[List[float], np.ndarray], - backend: str, - optimization_level: int, - resilience_level: int, - shots: int, - service: Optional[Union[QiskitRuntimeService, Dict[str, Any]]] = None, - optimizer: Optional[Optimizer] = None, - use_local_simulator: bool = False + molecule: Molecule, + initial_point: Union[List[float], np.ndarray], + backend: str, + optimization_level: int, + resilience_level: int, + shots: int, + service: Optional[Union[QiskitRuntimeService, Dict[str, Any]]] = None, + optimizer: Optional[Optimizer] = None, + use_local_simulator: bool = False ): """Energy calculation using hardware efficient ansatz with VQE @@ -53,7 +53,7 @@ def ground_state_solve( energy """ # setup service - if service and isinstance(service, dict): + if service and isinstance(service, dict) and not use_local_simulator: service = QiskitRuntimeService(**service) optimizer = optimizer or COBYLA(maxiter=500) @@ -73,7 +73,7 @@ def ground_state_solve( ) operator = qubit_converter.convert( - es_problem.second_q_ops()[0], + es_problem.second_q_ops()["ElectronicEnergy"], num_particles=es_problem.num_particles, ) @@ -106,7 +106,7 @@ def ground_state_solve( if use_local_simulator is True: estimator = QiskitEstimator() - + vqe = VQE( estimator=estimator, ansatz=ansatz, @@ -136,15 +136,15 @@ def ground_state_solve( def electronic_structure_problem( - molecules: List[Molecule], - initial_points: Optional[List[List[float]]] = None, - service: Optional[QiskitRuntimeService] = None, - backends: Optional[List[IBMQBackend]] = None, - optimization_level: int = 1, - resilience_level: int = 0, - shots: int = 4000, - optimizer: Optional[Optimizer] = None, - use_local_simulator: bool = False + molecules: List[Molecule], + initial_points: Optional[List[List[float]]] = None, + service: Optional[QiskitRuntimeService] = None, + backends: Optional[List[IBMQBackend]] = None, + optimization_level: int = 1, + resilience_level: int = 0, + shots: int = 4000, + optimizer: Optional[Optimizer] = None, + use_local_simulator: bool = False ): """Parallel VQE energy calculation using hardware efficient ansatz @@ -162,7 +162,9 @@ def electronic_structure_problem( Returns: list of VQE energies """ - service = service or QiskitRuntimeService() + service_account: Dict[str, Any] = {} + if service is not None and isinstance(service, QiskitRuntimeService): + service_account = service.active_account() initial_points = initial_points or [None] * len(molecules) backends = backends or [None] * len(molecules) @@ -174,7 +176,7 @@ def electronic_structure_problem( optimization_level=optimization_level, resilience_level=resilience_level, shots=shots, - service=service.active_account(), + service=service_account, optimizer=optimizer, use_local_simulator=use_local_simulator, ) @@ -182,3 +184,42 @@ def electronic_structure_problem( ] return get(function_references) + + +if __name__ == '__main__': + serverless = QuantumServerless() + + USE_RUNTIME = False + + service = None + backends = None + if USE_RUNTIME: + service = QiskitRuntimeService() + names = ["ibmq_qasm_simulator", "ibmq_qasm_simulator", "ibmq_qasm_simulator"] + backends = [service.backend(name) for name in names] + + with serverless: + energies = electronic_structure_problem( + molecules=[ + Molecule(geometry=[("H", [0.0, 0.0, 0.0]), ("Li", [0.0, 0.0, 1.0])], charge=0, multiplicity=1), + Molecule(geometry=[("H", [0.0, 0.0, 0.0]), ("Li", [0.0, 0.0, 1.5])], charge=0, multiplicity=1), + Molecule(geometry=[("H", [0.0, 0.0, 0.0]), ("Li", [0.0, 0.0, 2.0])], charge=0, multiplicity=1), + ], + initial_points=[ + [0.1, 0.1, 0.1, 0.1], + [0.01, 0.01, 0.01, 0.01], + [0.001, 0.001, 0.001, 0.001], + ], + service=service, + backends=backends, + optimization_level=1, + resilience_level=1, + shots=4000, + optimizer=SPSA(), + use_local_simulator=not USE_RUNTIME + ) + + print("LiH experiment results:") + print("Energies: ", [e[0] for e in energies]) + print("Shifts: ", [e[1] for e in energies]) + print("Energy + shift: ", [e[0] + e[1] for e in energies])