{ "cells": [ { "cell_type": "markdown", "id": "345cdcd4fc84356", "metadata": {}, "source": [ "# Remote Computing" ] }, { "cell_type": "markdown", "id": "6ba3240f621f8ae4", "metadata": {}, "source": [ "In this tutorial, we are going to send computations on remote platforms using Perceval. A \"platform\" is an online simulator or an actual physical photonic QPU available through a Cloud provider.\n", "\n", "The main provider is the Quandela Cloud but please note that others exist, see [providers](https://perceval.quandela.net/docs/reference/providers.html) for additional information." ] }, { "cell_type": "markdown", "id": "9196a53b730dcd34", "metadata": {}, "source": [ "## I. Updated Hello World\n", "\n", "Remember the *Hello World* code from the *Getting Started* page? Let's update it in order to run the same simulation on a remote platform." ] }, { "cell_type": "code", "execution_count": 1, "id": "1305dd0510f1fecb", "metadata": {}, "outputs": [], "source": [ "import time\n", "import math\n", "from pprint import pprint\n", "from tqdm.notebook import tqdm\n", "\n", "from perceval import BS, PS, BasicState, RemoteConfig, Experiment, ExecutionFactory, RemoteComputer, QuandelaCommunicationLayer, pdisplay, NoiseModel, acquire" ] }, { "cell_type": "code", "execution_count": 3, "id": "9382b93a70440344", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Samples: {\n", " |2,0>: 115\n", " |0,2>: 128\n", " |1,1>: 24\n", " |1,0>: 4829\n", " |0,1>: 4904\n", "}\n", "Probabilities: {\n", "\t|1,0>: 0.487179\n", "\t|1,1>: 0.001923\n", "\t|0,1>: 0.487179\n", "\t|0,2>: 0.011859\n", "\t|2,0>: 0.011859\n", "}\n" ] } ], "source": [ "# The first few lines remain unchanged\n", "experiment = Experiment(BS())\n", "experiment.with_input(BasicState(\"|1,1>\"))\n", "experiment.min_detected_photons_filter(1)\n", "\n", "noise_model = NoiseModel(transmittance=0.05, indistinguishability=0.85)\n", "\n", "# In this version, the local SimulatedComputer is replaced by a RemoteComputer which is constructed slightly differently:\n", "# - It takes a CommunicationLayer that is able to talk to one provider. Here, we will use the Quandela one, constructed like this:\n", "# - The back-end name \"SLOS\" is replaced by the name of the platform we want to send our computation on (here, \"sim:slos\").\n", "# - The 2nd parameter is an authentication token to the Cloud provider we're using (by default, the Quandela Cloud).\n", "# Let's assume we have a valid token, for now. We'll see how to generate one, later on, in this tutorial.\n", "# - Noise parameters can still be set, since this is a simulation platform\n", "computer = RemoteComputer(QuandelaCommunicationLayer(\"sim:slos\", \"a valid authentication token\"))\n", "computer.noise = noise_model\n", "\n", "# Starting from here, SimulatedComputer and RemoteComputer are fully interchangeable\n", "# Here, the max_shots_per_call parameter is required to limit your credit usage on the Cloud\n", "factory = ExecutionFactory(computer, experiment, max_shots_per_call=10_000)\n", "with acquire(computer):\n", " samples = factory.sample_count(10_000)['results']\n", " probs = factory.probs()['results']\n", " print(f\"Samples: {samples}\")\n", " print(f\"Probabilities: {probs}\")" ] }, { "cell_type": "markdown", "id": "6c5dc50ec86e533", "metadata": {}, "source": [ "Similar enough, isn't it?" ] }, { "cell_type": "markdown", "id": "260e69677a1ea3c9", "metadata": {}, "source": [ "*A quick note on the* `with acquire(computer):` *line:*\n", "\n", "On most computers, this line will do nothing. However, there are some providers that require to start a session before launching executions. This context manager starts that session at entering and stops it at exiting. For versatility, it is thus highly recommended that this line is always written, no matter which computer is used. It must be placed at the topmost level of the usage of the computer, typically at the same level as instantiation and destruction, so that start and stop are called only once (calling them several times could lead to disastrous behaviour).\n", "\n", "If this is not possible or not wished to call this in your code, you can also call the `computer.start()` and `computer.stop()` methods manually, but nothing will guarantee that the `stop()` method is executed in case of errors.\n", "\n", "Also, it can be replaced by a `with computer.acquire()` call, but the `acquire()` method can take several computers at once." ] }, { "cell_type": "markdown", "id": "6e24c77b8588ff47", "metadata": {}, "source": [ "## II. Preparing for remote computing\n", "\n", "Connecting to a remote provider requires a bit of configuration. You need to be able to connect and authenticate to the remote service.\n", "\n", "Quandela Cloud authentication is managed through *user tokens*. These are created on the Cloud website, from your user account page. If you haven't done so beforehand, please visit [cloud.quandela.com](https://cloud.quandela.com) and create an account. You'll be able to check what platforms are available to you, as well as their specifications.\n", "You have to generate a token in order to use any platform on the Cloud using a Perceval script. A token is personal and should not be shared. You can create as many as you wish on a single account.\n", "\n", "You can set your connection information up once and for all on a given computer, using Perceval persistent data system:" ] }, { "cell_type": "code", "execution_count": 3, "id": "bfc91a8d9ac67e6c", "metadata": {}, "outputs": [], "source": [ "# Save your token, cloud url and proxy configuration in a RemoteConfig instance, then call save().\n", "# You only need to do this once per machine, data will be shared among different Perceval installs on the same machine.\n", "# If your token changes, you'll need to redo this step once.\n", "remote_config = RemoteConfig() # The RemoteConfig is for the Quandela Provider\n", "remote_config.set_token(\"MY_TOKEN\")\n", "remote_config.set_url(\"https://api.cloud.quandela.com\") # Optional, by default the url is https://api.cloud.quandela.com\n", "remote_config.set_proxies({\"https\": \"socks5h://USER:PASSWORD@HOST:PORT\"}) # Optional proxy configuration\n", "remote_config.save()" ] }, { "cell_type": "markdown", "id": "7271586378d04ba7", "metadata": {}, "source": [ "
\n", "If you need to use multiple authentication information within the same script, you will have to enter the token value for each RemoteComputer, as shown in the updated Hello World.
| state | count |
|---|---|
| |0,1> | 94910 |
| |1,0> | 94788 |
| |1,1> | 5497 |
| |0,2> | 2425 |
| |2,0> | 2369 |
| |1,2> | 7 |
| |2,1> | 4 |
| state | count |
|---|---|
| |0,1> | 99079 |
| |1,0> | 94286 |
| |2,0> | 2628 |
| |1,1> | 2064 |
| |0,2> | 1935 |
| |2,1> | 5 |
| |1,2> | 3 |