{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "4046fd82",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Inizia a usare Qiskit in classe\"\n",
        "description: \"Scopri le basi dell'informatica quantistica e come eseguire il tuo primo circuito quantistico con Qiskit.\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore checkmark ccnot */}\n",
        "\n",
        "<span id=\"get-started-with-qiskit-in-the-classroom\" />\n",
        "\n",
        "# Inizia a usare Qiskit in classe\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a84d2a96-7885-4f6c-b34a-f2d386d4e120",
      "metadata": {},
      "source": [
        "Per questo modulo Qiskit in Classrooms, gli studenti devono avere un ambiente Python funzionante con i seguenti pacchetti installati:\n",
        "\n",
        "* `qiskit` v2.1.0 o più recente\n",
        "* `qiskit-ibm-runtime` v0.40.1 o più recente\n",
        "* `qiskit-aer` v0.17.0 o più recente\n",
        "* `qiskit.visualization`\n",
        "* `numpy`\n",
        "* `pylatexenc`\n",
        "\n",
        "Per configurare e installare i pacchetti di cui sopra, consultare la guida [Installare Qiskit](/docs/guides/install-qiskit).\n",
        "Per poter eseguire i lavori su computer quantistici reali, gli studenti dovranno creare un account su IBM Quantum® seguendo i passaggi della guida [Set up your IBM Cloud® account](/docs/guides/cloud-setup).\n",
        "\n",
        "Questo modulo è stato testato e ha utilizzato 2 secondi di tempo della QPU su un processore Heron v2. Si tratta solo di una stima. L'utilizzo effettivo può variare.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "d611274c-5988-45b7-98bf-01c57edc0b02",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Uncomment and modify this line as needed to install dependencies\n",
        "#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9a7cc00a-e11d-46e7-9737-1ec7a3fa9951",
      "metadata": {},
      "source": [
        "<span id=\"introduction\" />\n",
        "\n",
        "## Introduzione\n",
        "\n",
        "Nei moduli di Qiskit in the Classroom, avrete l'opportunità di utilizzare un computer quantistico per esplorare vari concetti di informatica quantistica e campi affini come la meccanica quantistica, l'informatica, la chimica e altro ancora. Questo modulo serve come prerequisito agli altri: introduce i fondamenti dell'informatica quantistica e come utilizzare Qiskit per eseguire circuiti quantistici.\n",
        "\n",
        "Prima vi daremo una breve panoramica del funzionamento di un computer classico, poi vi mostreremo come questi concetti vengono adattati al paradigma dell'informatica quantistica. Infine, vi mostreremo come mettere insieme questi concetti per costruire ed eseguire il vostro primo circuito quantistico.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "742678ad-9e14-4691-bc6f-5900c7f45f9b",
      "metadata": {},
      "source": [
        "<span id=\"classical-computers\" />\n",
        "\n",
        "## Computer classici\n",
        "\n",
        "Probabilmente conoscete le basi del funzionamento dei computer classici, ma in questa sede ne evidenzieremo alcune caratteristiche fondamentali per poter poi fare un confronto con i computer quantistici.\n",
        "\n",
        "<span id=\"the-basic-units-of-information-bits\" />\n",
        "\n",
        "### Le unità fondamentali dell'informazione: i bit\n",
        "\n",
        "I computer classici elaborano informazioni classiche e l'unità fondamentale dell'informazione classica è il *bit*. Un singolo bit può memorizzare la risposta a una domanda \"sì/no\". Di solito rappresentiamo i due stati binari di un bit come \"0\" e \"1\".\n",
        "\n",
        "<span id=\"review-of-binary-numbers\" />\n",
        "\n",
        "#### Riesame dei numeri binari\n",
        "\n",
        "La combinazione di bit consente di memorizzare più informazioni. Ad esempio, se si vuole memorizzare un numero da 0 a 15, lo si può fare con quattro bit nel modo seguente:\n",
        "\n",
        "|          |          |           |           |\n",
        "| :------- | :------: | :-------: | --------: |\n",
        "| 0 = 0000 | 4 = 0100 |  8 = 1000 | 12 = 1100 |\n",
        "| 1 = 0001 | 5 = 0101 |  9 = 1001 | 13 = 1101 |\n",
        "| 2 = 0010 | 6 = 0110 | 10 = 1010 | 14 = 1110 |\n",
        "| 3 = 0011 | 7 = 0111 | 11 = 1011 | 15 = 1111 |\n",
        "\n",
        "In generale, per convertire un numero binario di $N$ bit in un numero familiare, base-10 si moltiplica il bit meno significativo (quello più a destra) per $2^0 = 1$, il bit successivo a sinistra per $2^1 = 2$, poi quello successivo per $2^2 = 4$, e così via, fino a raggiungere il bit più significativo (quello più a sinistra), che si moltiplica $2^{N-1}$.\n",
        "\n",
        "Ciò significa che $N$ bit possono trovarsi in uno dei $2^N$ diversi stati possibili.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Quanti bit sono necessari per rappresentare il numero 86? Scrivere la stringa di bit che codifica questo numero in binario.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    Ricordate che $N$ bit permette di rappresentare i numeri da $0$ a $2^N - 1$, quindi usando sei bit si arriva a $2^6 - 1 = 63$. Non è abbastanza. Aggiungiamo un altro bit per arrivare a $2^7 - 1 = 127$. Ora scomponiamo 86 in potenze di 2:\n",
        "\n",
        "    $$\n",
        "    \\begin{aligned}\n",
        "    86 &= 64 + 16 + 4 + 2 \\\\\n",
        "    &= 2^6 \\times 1 + 2^5 \\times 0 + 2^4 \\times 1 + 2^3 \\times 0 + 2^2 \\times 1 + 2^1 \\times 1 + 2^0 \\times 0 \\\\\n",
        "    &= 1010110\n",
        "    \\end{aligned}\n",
        "    $$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "<span id=\"fundamental-operations-gates\" />\n",
        "\n",
        "### Operazioni fondamentali: porte logiche\n",
        "\n",
        "Ora, un computer deve essere in grado di *fare* qualcosa con i bit per poter, beh, calcolare. Le porte binarie sono le operazioni che costituiscono i mattoni fondamentali di tutti gli algoritmi e i codici più complicati.\n",
        "\n",
        "<span id=\"single-bit-gate\" />\n",
        "\n",
        "### Porta a bit singolo:\n",
        "\n",
        "<span id=\"not\" />\n",
        "\n",
        "#### NON\n",
        "\n",
        "Quando si dispone di un solo bit, c'è un solo modo per trasformarne lo stato: capovolgere lo stato da 0 a 1 o da 1 a 0. Questo è il cancello \"NOT\". L'effetto di questo gate - e degli altri gate di cui parleremo in seguito - può essere rappresentato in una cosiddetta \"tabella della verità\", con colonne per gli stati di ingresso e di uscita dei qubit. La tabella di verità per la porta NOT è:\n",
        "\n",
        "| Immissione | Emissione |\n",
        "| :--------- | --------: |\n",
        "| 0          |         1 |\n",
        "| 1          |         0 |\n",
        "\n",
        "<span id=\"multi-bit-gates\" />\n",
        "\n",
        "### Porte multi-bit:\n",
        "\n",
        "<span id=\"and\" />\n",
        "\n",
        "#### E\n",
        "\n",
        "AND è una porta a due bit che prende due bit in ingresso ed emette un singolo bit. L'uscita è 1 se entrambi i bit di ingresso sono 1 e 0 altrimenti:\n",
        "\n",
        "| Immissione | Emissione |\n",
        "| :--------- | --------: |\n",
        "| 00         |         0 |\n",
        "| 01         |         0 |\n",
        "| 10         |         0 |\n",
        "| 11         |         1 |\n",
        "\n",
        "<span id=\"or\" />\n",
        "\n",
        "#### OPPURE\n",
        "\n",
        "L'OR è un altro gate a due bit con un singolo bit di uscita. L'output è 1 se *uno dei due* bit è 1:\n",
        "\n",
        "| Immissione | Emissione |\n",
        "| :--------- | --------: |\n",
        "| 00         |         0 |\n",
        "| 01         |         1 |\n",
        "| 10         |         1 |\n",
        "| 11         |         1 |\n",
        "\n",
        "<span id=\"xor\" />\n",
        "\n",
        "#### XOR\n",
        "\n",
        "XOR è l'acronimo di \"OR esclusivo\" ed è simile al gate OR, ma produce un risultato pari a 1 se *solo uno* dei bit in ingresso è pari a 1. Il risultato è 0 se i due valori sono entrambi 1 o entrambi 0:\n",
        "\n",
        "| Immissione | Emissione |\n",
        "| :--------- | --------: |\n",
        "| 00         |         0 |\n",
        "| 01         |         1 |\n",
        "| 10         |         1 |\n",
        "| 11         |         0 |\n",
        "\n",
        "<span id=\"measurements\" />\n",
        "\n",
        "### Misurazioni\n",
        "\n",
        "In genere, quando si apprende l'informatica classica, non si presta molta attenzione al processo di lettura dello stato dei bit. Questo perché non è molto complesso dal punto di vista concettuale. È possibile misurare i bit in qualsiasi momento, prima, durante o dopo un calcolo, senza che ciò influisca sul risultato. Questo non è il caso dell'informatica quantistica, come vedremo di seguito.\n",
        "\n",
        "<span id=\"circuits\" />\n",
        "\n",
        "### Circuiti:\n",
        "\n",
        "Combinando le porte di cui sopra, è possibile eseguire qualsiasi tipo di operazione su un computer. Facciamo un semplice esempio: Utilizzando le porte AND e XOR, si può costruire il circuito a mezza scala, che calcola la somma di due bit. Questo viene rappresentato in un diagramma di circuito logico, dove i fili rappresentano i bit e le porte che operano sui bit sono indicate come simboli sui fili corrispondenti:\n",
        "\n",
        "![Schema classico del circuito a mezza scala. Un gate XOR genera il bit di uscita Sum e un gate AND genera il bit di uscita Carry.](https://quantum.cloud.ibm.com/learning/images/modules/quantum-mechanics/get-started-with-qiskit/classicaladder.avif)\n",
        "\n",
        "Quindi, i due bit vengono copiati e fatti passare attraverso un gate AND e un gate XOR. Il risultato del gate XOR è il \"bit di somma\" (S), che rimane nel posto uno del numero binario, mentre il risultato del gate AND è il \"bit di riporto\" (C), che è il valore della cifra successiva più significativa del numero binario. Ecco la tabella della verità:\n",
        "\n",
        "| $A$ | $B$ | Somma ( $A \\oplus B$ ) | Trasporto ( $A \\wedge B$ ) |\n",
        "| --- | --- | ---------------------- | -------------------------- |\n",
        "| 0   | 0   | 0                      | 0                          |\n",
        "| 0   | 1   | 1                      | 0                          |\n",
        "| 1   | 0   | 1                      | 0                          |\n",
        "| 1   | 1   | 0                      | 1                          |\n",
        "\n",
        "<span id=\"check-your-understanding-1\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Verificate che la tabella di verità di cui sopra fornisca la soluzione corretta per un circuito sommatore. Ovvero, per ognuna delle quattro opzioni di A e B, verificare che $A+B=S+2 \\times C$.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    $$\n",
        "    \\begin{aligned}\n",
        "    0+0 &= 0+0 = 0 ~\\checkmark \\\\\n",
        "    0+1 &= 1+0 = 1  ~\\checkmark \\\\\n",
        "    1+0 &= 1+0 = 1  ~\\checkmark \\\\\n",
        "    1+1 &= 0+2 = 2 ~\\checkmark \\\\\n",
        "    \\end{aligned}\n",
        "    $$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a324a959-5edc-4aaf-91ad-6bef9ab7c435",
      "metadata": {},
      "source": [
        "<span id=\"quantum-computers\" />\n",
        "\n",
        "## Computer quantistici\n",
        "\n",
        "<span id=\"bits-$rightarrow$-qubits\" />\n",
        "\n",
        "### Bit $\\rightarrow$ qubit\n",
        "\n",
        "Così come i bit sono le unità fondamentali dell'informazione classica, i bit *quantistici*, o \"qubit\", sono le unità fondamentali dell'informazione quantistica. Come il bit classico, lo stato di un qubit può essere 0 o 1, che in genere indichiamo con $\\vert 0\\rangle$ e $\\vert 1\\rangle$. Ma, a differenza del bit classico, un bit quantistico può anche trovarsi contemporaneamente in una *sovrapposizione* dello stato $\\vert 0\\rangle$ e dello stato $\\vert 1\\rangle$. In generale, un qubit può trovarsi in qualsiasi stato $\\vert \\psi\\rangle$ della forma:\n",
        "\n",
        "$$\n",
        "\\vert \\psi\\rangle = c_0 \\vert 0\\rangle + c_1 \\vert 1\\rangle\n",
        "$$\n",
        "\n",
        "dove $c_0$ e $c_1$ sono ampiezze complesse con $\\vert c_0 \\vert ^2+\\vert c_1\\vert ^2=1$.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "11563bfb-93d4-4a6a-9bd9-b52665ab4517",
      "metadata": {},
      "source": [
        "<span id=\"the-quantum-phase\" />\n",
        "\n",
        "#### La fase quantistica\n",
        "\n",
        "Poiché $c_0$ e $c_1$ sono complessi, possono essere scritti ciascuno come $c_i = \\vert c_i\\vert e^{i\\phi_i}$ dove $\\phi_i$ è chiamata *fase*. Se moltiplichiamo l'intero stato per lo stesso fattore di fase globale, non cambia nulla dal punto di vista fisico: si tratta della cosiddetta fase globale, che non ha conseguenze osservabili.\n",
        "\n",
        "Per questo motivo, è convenzionale \"escludere\" $e^{i\\phi_0}$, dando:\n",
        "\n",
        "$\\vert \\psi\\rangle = \\vert c_0\\vert \\vert 0\\rangle + \\vert c_1\\vert e^{i\\phi}\\vert 1\\rangle$\n",
        "\n",
        "dove $\\phi = \\phi_1-\\phi_0$ è la fase *relativa* dello stato quantistico, che *ha* conseguenze osservabili.\n",
        "\n",
        "Questa fase gioca un ruolo molto importante nel calcolo quantistico e ne esplorerete le varie conseguenze nei successivi moduli di Qiskit in the Classroom.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c35a8265-2d19-4743-99ac-39192e46f59a",
      "metadata": {},
      "source": [
        "<span id=\"multiple-qubits\" />\n",
        "\n",
        "#### Qubit multipli\n",
        "\n",
        "Mentre lo stato di più bit potrebbe essere espresso semplicemente come una stringa di 0s e 1s, lo stato di più qubit diventa un po' più complicato a causa dei principi di *sovrapposizione* e di *entanglement*.\n",
        "\n",
        "Ricordiamo che $N$ bit può trovarsi in uno dei $2^N$ possibili stati che vanno dai numeri binari 000...000 a 111...111. Ma ora, grazie al principio di sovrapposizione, i *qubit di* $N$ possono trovarsi in una sovrapposizione di *tutti* questi stati contemporaneamente!\n",
        "\n",
        "Questo può essere espresso come\n",
        "\n",
        "$$\n",
        "\\psi_N = \\sum_{i=0}^{2^N-1} c_i \\vert i\\rangle\n",
        "$$\n",
        "\n",
        "dove, come nel caso classico, lo stato $\\vert i\\rangle$ corrisponde allo stato in cui ogni qubit si trova nella giusta combinazione di 0s e 1s per produrre il numero binario $i$. Questi sono noti come \"stati base computazionali\" del sistema quantistico. Ad esempio, uno stato a tre qubit può essere scritto come una sovrapposizione degli otto stati della sua base computazionale:\n",
        "\n",
        "$$\n",
        "\\psi_3 = c_0 \\vert 000\\rangle + c_1 \\vert 001\\rangle + c_2 \\vert 010\\rangle + c_3 \\vert 011\\rangle + c_4 \\vert 100\\rangle + c_5 \\vert 101\\rangle + c_6 \\vert 110\\rangle + c_7 \\vert 111\\rangle\n",
        "$$\n",
        "\n",
        "Ogni qubit del sistema è indicato con un indice da $0$ a $N-1$. La convenzione è di leggere gli stati dei qubit da destra a sinistra, in modo che lo stato del qubit $0$ sia lo stato più a destra e quello del qubit $N-1$ sia il più a sinistra. Questa è nota come notazione \"little-endian\" e può sembrare controintuitiva all'inizio, dato che siamo abituati a leggere da sinistra a destra.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "A prima vista, può sembrare controintuitivo ordinare i qubit da destra a sinistra come nella notazione little-endian, ma in realtà è una cosa molto logica! Spiegare perché. (Ricordiamo la discussione precedente sulla conversione dei numeri da binari a base-10 )\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    Se ordiniamo i qubit da destra a sinistra, in modo che il qubit 0 sia il più lontano a destra e il qubit N-1 sia il più lontano a sinistra, è logico associare il qubit $0$ al bit meno significativo, che viene moltiplicato per $2^0$ e il qubit $N-1$ al bit più significativo, che viene moltiplicato per $2^{N-1}$.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "<span id=\"entanglement\" />\n",
        "\n",
        "#### Intreccio\n",
        "\n",
        "Come abbiamo detto in precedenza, un'altra caratteristica fondamentale dei qubit è che possono essere *entangled* l'uno con l'altro. Prendiamo un esempio di uno stato a due qubit, dove $c_0 = c_3 = \\frac{1}{\\sqrt{2}}$ e $c_1 = c_2 = 0$ :\n",
        "\n",
        "$\\vert \\psi\\rangle = \\frac{1}{\\sqrt{2}}(\\vert 00\\rangle + \\vert 11\\rangle)$\n",
        "\n",
        "Quindi, lo stato del qubit 0 può essere $\\vert 0\\rangle$ o $\\vert 1\\rangle$ con la stessa probabilità, e lo stesso vale per lo stato del qubit 1. Ma queste probabilità non sono più indipendenti l'una dall'altra. Se troviamo che lo stato del qubit 0 è $\\vert 0\\rangle$, allora *sappiamo* che anche il qubit 1 sarà in $\\vert 0\\rangle$. Questo è vero a prescindere dalla distanza tra i due, ed è per questo che l'atto di misurare uno stato entangled viene talvolta definito \"azione spettrale a distanza\"\n",
        "\n",
        "L'entanglement può assumere anche altre forme. Ad esempio, lo Stato\n",
        "\n",
        "$\\vert \\psi\\rangle = \\frac{1}{\\sqrt{2}}(\\vert 01\\rangle + \\vert 10\\rangle)$\n",
        "\n",
        "produce ogni volta esiti opposti: se un qubit viene misurato $\\vert 0\\rangle$, è garantito che l'altro si trovi nello stato $\\vert 1\\rangle$.\n",
        "\n",
        "<span id=\"check-your-understanding-1\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Lo stato $\\vert \\psi\\rangle = \\vert 11\\rangle$ è ingarbugliato? Perché o perché no?\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    Non è impigliato. Se i risultati sono sempre gli stessi quando si misurano entrambi i qubit, ciò è dovuto al fatto che ogni qubit è sempre fissato nello stato $\\vert 1\\rangle$. Il risultato della misurazione di un qubit non dipende in realtà dall'altro: entrambi sono sempre $\\vert 1\\rangle$.\n",
        "\n",
        "    In generale, se è possibile descrivere lo stato di ciascun qubit separatamente e poi moltiplicarli insieme in questo modo:\n",
        "\n",
        "    $\\vert \\psi\\rangle = \\vert \\psi_1\\rangle \\vert \\psi_0\\rangle $\n",
        "\n",
        "    In questo caso si parla di \"stato prodotto\" e *non è* entangled.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "<span id=\"vector-notation\" />\n",
        "\n",
        "#### Notazione vettoriale\n",
        "\n",
        "Spesso è utile usare vettori e matrici per vedere come si trasforma lo stato quantistico con diverse operazioni. In questa rappresentazione, i nostri stati quantistici saranno vettori e le nostre porte quantistiche (discusse nella prossima sezione) saranno matrici che trasformano i vettori.\n",
        "\n",
        "Per un singolo qubit, la forma vettoriale degli stati è scelta come segue: $\\vert 0\\rangle = \\begin{pmatrix}1 \\\\ 0\\end{pmatrix}$ $\\vert 1\\rangle = \\begin{pmatrix}0 \\\\ 1\\end{pmatrix}$ In questo modo, uno stato arbitrario $\\vert \\psi\\rangle = a\\vert 0\\rangle+b\\vert 1\\rangle$ può essere scritto come $\\vert \\psi\\rangle =\\begin{pmatrix}a \\\\ b\\end{pmatrix}$\n",
        "\n",
        "Per uno stato generale, $n$ -qubit, avremo bisogno di un vettore $2^n$ -dimensionale, con gli stati base ordinati come ci si potrebbe aspettare, in valore binario crescente:\n",
        "\n",
        "$$\n",
        "\\vert 0 \\dots 000\\rangle = \\begin{pmatrix}1 \\\\ 0 \\\\ 0 \\\\ \\vdots \\\\ 0\\end{pmatrix}, \\vert 0 \\dots 001 \\rangle = \\vert 1 \\dots 110\\rangle = \\begin{pmatrix}0 \\\\ \\vdots \\\\ 0 \\\\ 1 \\\\ 0\\end{pmatrix}, \\vert 1 \\dots 111 \\rangle = \\begin{pmatrix}0 \\\\ \\vdots \\\\ 0 \\\\ 0\\\\ 1\\end{pmatrix}\n",
        "$$\n",
        "\n",
        "Tenendo presente questa scelta di notazione vettoriale, possiamo introdurre le porte quantistiche necessarie, i loro effetti sugli stati quantistici e le loro forme matriciali.\n",
        "\n",
        "<span id=\"check-your-understanding-2\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Esistono quattro stati base computazionali per un sistema a due qubit. Scrivete ciascuno di essi sia in notazione ket che vettoriale.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    $$\n",
        "    \\vert 00\\rangle = \\begin{pmatrix}1 \\\\ 0 \\\\ 0 \\\\ 0\\end{pmatrix}, \\vert 01 \\rangle = \\begin{pmatrix}0 \\\\ 1 \\\\ 0 \\\\ 0\\end{pmatrix}, \\dots, \\vert 10\\rangle = \\begin{pmatrix}0 \\\\ 0 \\\\ 1 \\\\ 0\\end{pmatrix}, \\vert 11 \\rangle = \\begin{pmatrix}0 \\\\ 0 \\\\ 0\\\\ 1\\end{pmatrix}\n",
        "    $$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "52f971a7-4a5e-4571-927b-23a642fae997",
      "metadata": {},
      "source": [
        "<span id=\"gates-$rightarrow$-quantum-gates\" />\n",
        "\n",
        "## Gates $\\rightarrow$ i gate quantistici\n",
        "\n",
        "Così come le porte classiche come NOT, AND, OR e XOR possono essere combinate per costruire circuiti classici arbitrari, le porte quantistiche svolgono lo stesso ruolo nell'informatica quantistica. Poiché i qubit hanno caratteristiche meccaniche quantistiche aggiuntive, le porte quantistiche sono di conseguenza più ricche. Sebbene sia ancora possibile descrivere la loro azione sulla base degli stati $|0\\rangle$ e $|1\\rangle$ con una tabella di verità, questo non cattura l'intero quadro. Per le porte quantistiche è spesso più naturale utilizzare una rappresentazione matriciale, poiché agiscono anche su sovrapposizioni di stati base.\n",
        "\n",
        "Di seguito presenteremo le porte quantistiche più comuni e come trasformano i qubit con cui interagiscono. Se del caso, li collegheremo alle porte classiche già conosciute.\n",
        "\n",
        "<span id=\"single-qubit-gates\" />\n",
        "\n",
        "### Porte a singolo qubit\n",
        "\n",
        "**$X$ gate** : È l'equivalente quantistico di un'operazione NOT. La sua tabella di verità assomiglia esattamente alla classica porta NOT:\n",
        "\n",
        "| Immissione       |        Emissione |\n",
        "| :--------------- | ---------------: |\n",
        "| $\\vert 0\\rangle$ | $\\vert 1\\rangle$ |\n",
        "| $\\vert 1\\rangle$ | $\\vert 0\\rangle$ |\n",
        "\n",
        "E la rappresentazione matriciale:\n",
        "\n",
        "$X=\\begin{pmatrix} 0 & 1 \\\\ 1 & 0 \\end{pmatrix}$\n",
        "\n",
        "In Qiskit, la creazione di un circuito con una porta $X$ si presenta come segue:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "6c215e46-26cb-4e10-a1d7-2eecd2c18294",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/6c215e46-26cb-4e10-a1d7-2eecd2c18294-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "\n",
        "qc = QuantumCircuit(1)\n",
        "qc.x(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3a59abe3-5e75-4ff1-9f5e-9b24fd5c5ea0",
      "metadata": {},
      "source": [
        "In questo schema circuitale molto semplice, il qubit è rappresentato da un filo, la linea nera orizzontale, e il gate è rappresentato da una casella su quel filo.\n",
        "\n",
        "**Porta di Hadamard:** Crea uno stato di sovrapposizione. Tabella di verità:\n",
        "\n",
        "| Immissione       |                                                      Emissione |\n",
        "| :--------------- | -------------------------------------------------------------: |\n",
        "| $\\vert 0\\rangle$ | $\\frac{1}{\\sqrt{2}}\\left(\\vert 0\\rangle+\\vert 1\\rangle\\right)$ |\n",
        "| $\\vert 1\\rangle$ | $\\frac{1}{\\sqrt{2}}\\left(\\vert 0\\rangle-\\vert 1\\rangle\\right)$ |\n",
        "\n",
        "Rappresentazione a matrice: $H=\\frac{1}{\\sqrt{2}}\\begin{pmatrix} 1 & 1 \\\\ 1 & -1 \\end{pmatrix}$\n",
        "\n",
        "Un circuito con una porta di Hadamard è realizzato come segue:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "1a009015-4ced-47e4-a18d-d0685e4cab47",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/1a009015-4ced-47e4-a18d-d0685e4cab47-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit import QuantumCircuit\n",
        "\n",
        "qc = QuantumCircuit(1)\n",
        "qc.h(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9de7658f-e456-4788-81bb-6900c12ef054",
      "metadata": {},
      "source": [
        "**$Z$ gate** : Aggiunge uno sfasamento di $\\Delta \\phi = \\pi$ allo stato $|1\\rangle$ :\n",
        "\n",
        "| Immissione       |         Emissione |\n",
        "| :--------------- | ----------------: |\n",
        "| $\\vert 0\\rangle$ |  $\\vert 0\\rangle$ |\n",
        "| $\\vert 1\\rangle$ | $-\\vert 1\\rangle$ |\n",
        "\n",
        "$Z=\\begin{pmatrix} 1 & 0 \\\\ 0 & -1 \\end{pmatrix}$\n",
        "\n",
        "In Qiskit, la creazione di un circuito con una porta $Z$ si presenta come segue:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "7bca3c98-884b-4709-bbe8-a9e16cc45698",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/7bca3c98-884b-4709-bbe8-a9e16cc45698-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)\n",
        "qc.z(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c9ee10a5-5f69-4db4-87e9-bc1d3cd051eb",
      "metadata": {},
      "source": [
        "**$T$ gate** : Aggiunge uno sfasamento di $\\Delta \\phi = \\pi/4$ allo stato $|1\\rangle$ :\n",
        "\n",
        "| Immissione       |                  Emissione |\n",
        "| :--------------- | -------------------------: |\n",
        "| $\\vert 0\\rangle$ |           $\\vert 0\\rangle$ |\n",
        "| $\\vert 1\\rangle$ | $e^{i\\pi/4}\\vert 1\\rangle$ |\n",
        "\n",
        "$T=\\begin{pmatrix} 1 & 0 \\\\ 0 & e^{i\\pi/4} \\end{pmatrix}$\n",
        "\n",
        "In Qiskit, la creazione di un circuito con una porta $T$ si presenta come segue:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "ac699059-6be5-4a1a-89cb-97b7af412ab8",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/ac699059-6be5-4a1a-89cb-97b7af412ab8-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(1)\n",
        "qc.t(0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "52b43ac8-be21-4652-a139-7093fe27fd69",
      "metadata": {},
      "source": [
        "<span id=\"multi-qubit-gates\" />\n",
        "\n",
        "### Porte multi-qubit\n",
        "\n",
        "Le porte a due qubit possono assomigliare alle porte classiche a due bit, ma con un'importante avvertenza: tutte le porte quantistiche devono essere reversibili. In termini di algebra lineare, ciò significa che sono rappresentati da matrici unitarie. Pertanto, due qubit in ingresso corrispondono sempre a due qubit in uscita e l'operazione può, in linea di principio, essere annullata. Ciò è in contrasto con le porte classiche viste in precedenza, come AND o OR, che perdono informazioni e sono irreversibili: data un'uscita, non è possibile determinare in modo univoco l'ingresso.\n",
        "\n",
        "**Porta CNOT (Controlled-NOT):** I due qubit in ingresso sono chiamati qubit di \"controllo\" e qubit di \"destinazione\". Il qubit di controllo rimane invariato, ma il suo stato determina ciò che accade al qubit di destinazione. Se il qubit di controllo si trova nello stato $\\vert 1\\rangle$, allora viene applicata una porta $X$ a quel target; se lo stato del qubit di controllo è $\\vert 0\\rangle$, non viene effettuata alcuna modifica. Nella notazione che segue, si assume che il qubit $A$ (il qubit più a destra) sia il controllo e il qubit $B$ (il qubit più a sinistra) sia il bersaglio. Di seguito, la notazione utilizzata è $CNOT(q_{control},q_{target})\\vert BA\\rangle.$\n",
        "\n",
        "$CNOT(A,B)\\vert BA\\rangle_{input} = \\vert BA\\rangle_{output}$\n",
        "\n",
        "| Immissione        |         Emissione |\n",
        "| :---------------- | ----------------: |\n",
        "| $\\vert 00\\rangle$ | $\\vert 00\\rangle$ |\n",
        "| $\\vert 01\\rangle$ | $\\vert 11\\rangle$ |\n",
        "| $\\vert 10\\rangle$ | $\\vert 10\\rangle$ |\n",
        "| $\\vert 11\\rangle$ | $\\vert 01\\rangle$ |\n",
        "\n",
        "Quindi, la matrice che rappresenta questa azione è:\n",
        "\n",
        "$CNOT=\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix}$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "1c4dc48d-3d2b-4b4b-b405-c93504815ba9",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/1c4dc48d-3d2b-4b4b-b405-c93504815ba9-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.cx(0, 1)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "be45af7b-a148-4b46-8379-3ac9658f50a9",
      "metadata": {},
      "source": [
        "Questo è il primo schema di circuito che vediamo con due qubit, rappresentati dai due fili. Il gate CNOT è implementato tra i due qubit, con $q_0$ come controllo e $q_1$ come target.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "La maggior parte delle porte ha la stessa forma matriciale in Qiskit come in qualsiasi altro luogo. Ma la porta CNOT agisce su due qubit, e quindi improvvisamente le convenzioni di ordinamento dei qubit diventano un problema. I testi che ordinano i qubit $\\vert q_0,q_1,...\\rangle$ mostreranno una forma matriciale diversa per le loro porte CNOT. Verificare con una moltiplicazione esplicita della matrice che la matrice CNOT di cui sopra abbia l'azione corretta sullo stato $\\vert 01\\rangle.$\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    $CNOT\\vert 01\\rangle =\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix}\\begin{pmatrix}0 \\\\ 1 \\\\ 0 \\\\0\\end{pmatrix} = \\begin{pmatrix}0 \\\\ 0 \\\\ 0 \\\\1\\end{pmatrix} = \\vert 11\\rangle$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "**Cancello SWAP:** Questo gate scambia gli stati di due qubit. Tabella di verità:\n",
        "\n",
        "| Immissione        |         Emissione |\n",
        "| :---------------- | ----------------: |\n",
        "| $\\vert 00\\rangle$ | $\\vert 00\\rangle$ |\n",
        "| $\\vert 01\\rangle$ | $\\vert 10\\rangle$ |\n",
        "| $\\vert 10\\rangle$ | $\\vert 01\\rangle$ |\n",
        "| $\\vert 11\\rangle$ | $\\vert 11\\rangle$ |\n",
        "\n",
        "Quindi, la matrice che rappresenta questa azione è:\n",
        "\n",
        "$SWAP=\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1\\end{pmatrix}$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "118da691-4208-4248-a21f-a5e22815dc2c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/118da691-4208-4248-a21f-a5e22815dc2c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.swap(0, 1)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "78199ae4-93e4-49a2-948a-f41a22187bae",
      "metadata": {},
      "source": [
        "La porta SWAP può essere costruita da tre CNOT. Per vedere come, possiamo `decompose()` il cancello con Qiskit:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "5efa09b9-b3e4-43fb-81f3-c33283a992d2",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/5efa09b9-b3e4-43fb-81f3-c33283a992d2-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(2)\n",
        "qc.swap(0, 1)\n",
        "qc.decompose().draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "330362e5-f040-426f-a6d9-d730c917c7f2",
      "metadata": {},
      "source": [
        "Qui vediamo per la prima volta come vengono rappresentate le porte multiple in un diagramma di circuito. La lettura avviene da sinistra a destra, quindi il gate più a sinistra viene applicato per primo.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Verificare che la combinazione di CNOT di cui sopra dia luogo a un gate SWAP. È possibile farlo con la moltiplicazione matriciale o con qualsiasi altro metodo.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    Con la moltiplicazione delle matrici:\n",
        "\n",
        "    $\\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix} \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0\\end{pmatrix} \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 1 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0\\end{pmatrix} = \\begin{pmatrix} 1 & 0 & 0 & 0 \\\\ 0 & 0 & 1 & 0 \\\\ 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 1\\end{pmatrix} = SWAP ~\\checkmark$\n",
        "\n",
        "    Usare una tabella di verità per vedere come cambiano gli stati con ogni CNOT. Nell'ultima colonna, gli stati devono essere equivalenti alla colonna \"output\" della tabella di verità SWAP:\n",
        "\n",
        "    | Immissione        |     CNOT(A,B)     |     CNOT(B,A)     |                    CNOT(A,B) |\n",
        "    | :---------------- | :---------------: | :---------------: | ---------------------------: |\n",
        "    | $\\vert 00\\rangle$ | $\\vert 00\\rangle$ | $\\vert 00\\rangle$ | $\\vert 00\\rangle \\checkmark$ |\n",
        "    | $\\vert 01\\rangle$ | $\\vert 11\\rangle$ | $\\vert 10\\rangle$ | $\\vert 10\\rangle \\checkmark$ |\n",
        "    | $\\vert 10\\rangle$ | $\\vert 10\\rangle$ | $\\vert 11\\rangle$ | $\\vert 01\\rangle \\checkmark$ |\n",
        "    | $\\vert 11\\rangle$ | $\\vert 01\\rangle$ | $\\vert 01\\rangle$ | $\\vert 11\\rangle \\checkmark$ |\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "**Porta di Toffoli (o \"controllata-controllata-NOT\" (CCNOT)):** Si tratta di una porta *a tre qubit*. Il nome \"controllato-controllato-NOT\" può già dirvi come funziona: ci sono due qubit di controllo e un qubit bersaglio, e lo stato del qubit bersaglio viene capovolto solo se *entrambi i* qubit di controllo sono nello stato $\\vert 1\\rangle$. Manteniamo la convenzione di ordinamento utilizzata con il CNOT:\n",
        "\n",
        "$$\n",
        "CCNOT(Control A, Control B, Target C)\\vert CBA\\rangle\n",
        "$$\n",
        "\n",
        "Quindi la tabella della verità è:\n",
        "\n",
        "| Immissione         |          Emissione |\n",
        "| :----------------- | -----------------: |\n",
        "| $\\vert 000\\rangle$ | $\\vert 000\\rangle$ |\n",
        "| $\\vert 001\\rangle$ | $\\vert 001\\rangle$ |\n",
        "| $\\vert 010\\rangle$ | $\\vert 010\\rangle$ |\n",
        "| $\\vert 011\\rangle$ | $\\vert 111\\rangle$ |\n",
        "| $\\vert 100\\rangle$ | $\\vert 100\\rangle$ |\n",
        "| $\\vert 101\\rangle$ | $\\vert 101\\rangle$ |\n",
        "| $\\vert 110\\rangle$ | $\\vert 110\\rangle$ |\n",
        "| $\\vert 111\\rangle$ | $\\vert 011\\rangle$ |\n",
        "\n",
        "La matrice che rappresenta questa azione è:\n",
        "\n",
        "$$\n",
        "CCNOT=\\begin{pmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\end{pmatrix}\n",
        "$$\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "d1829257-b7a4-49d9-8ac2-3d6230165427",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/d1829257-b7a4-49d9-8ac2-3d6230165427-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(3)\n",
        "qc.ccx(0, 1, 2)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "aa2e83e5-1197-473c-9f16-4c264b08aca0",
      "metadata": {},
      "source": [
        "Anche la porta di Toffoli, insieme ad altre porte, può essere decomposta in CNOT. Tuttavia, è significativamente più complicata della decomposizione della porta SWAP, quindi si lascerà come esercizio opzionale alla fine del modulo l'esplorazione e la verifica di questa decomposizione.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "970302ee-eccc-48eb-b255-4a2d7bc8fbbc",
      "metadata": {},
      "source": [
        "<span id=\"measurements\" />\n",
        "\n",
        "## Misurazioni\n",
        "\n",
        "Le misure svolgono un ruolo speciale nell'informatica quantistica, che non ha analoghi nell'informatica classica. Mentre nell'informatica classica si possono controllare i bit in qualsiasi momento a scelta durante un algoritmo, nell'informatica quantistica bisogna essere molto selettivi su quando guardare i qubit, perché la misurazione fa collassare il loro stato e distrugge la sovrapposizione che conferisce ai qubit la loro complessità computazionale.\n",
        "\n",
        "In particolare, dato uno stato quantistico $N$ -bit $\\vert \\psi\\rangle = \\sum_{i=0}^{2^N-1} c_i \\vert i\\rangle$, una misurazione farà collassare lo stato in una delle funzioni base $\\vert i\\rangle$ con una probabilità pari a $\\vert c_i\\vert ^2$.\n",
        "\n",
        "Ma questo effetto distruttivo di una misura non è sempre un ostacolo. È infatti una risorsa chiave in alcuni algoritmi e protocolli, come il [teletrasporto quantistico](/learning/modules/computer-science/quantum-teleportation) e la [distribuzione quantistica delle chiavi](/learning/modules/computer-science/quantum-key-distribution).\n",
        "\n",
        "In Qiskit, quando viene effettuata una misura, questa viene inviata a un registro classico dove viene memorizzata come un bit classico. La creazione di un circuito con una misura si presenta in questo modo:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "56dfec5d-556b-486d-9cbf-0700582ec25c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/56dfec5d-556b-486d-9cbf-0700582ec25c-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc = QuantumCircuit(\n",
        "    1, 1\n",
        ")  # the second number is the number of classical bits in the circuit\n",
        "qc.measure(0, 0)\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "45a53043-fdc8-4df2-b2c8-8b12ded1f400",
      "metadata": {},
      "source": [
        "<span id=\"circuits\" />\n",
        "\n",
        "## Circuiti\n",
        "\n",
        "Ora che sappiamo come funzionano i qubit, le porte e le misure, costruiamo ed eseguiamo il nostro circuito quantistico! A tal fine, è necessario introdurre un utile flusso di lavoro chiamato Qiskit patterns.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a5adf2d9-4de5-4978-b509-05fb7381f238",
      "metadata": {},
      "source": [
        "<span id=\"qiskit-patterns-framework\" />\n",
        "\n",
        "### Framework dei modelli Qiskit\n",
        "\n",
        "Il framework dei modelli Qiskit è una procedura generale per l'approccio e la risoluzione di problemi con un computer quantistico. Si compone di quattro fasi:\n",
        "\n",
        "1. **Mappare il** nostro problema in circuiti e operatori quantistici\n",
        "2. **Ottimizzazione** del circuito per l'hardware di destinazione\n",
        "3. **Esecuzione** su hardware di destinazione\n",
        "4. **Postelaborazione** dei risultati\n",
        "\n",
        "Per illustrare questi passaggi, implementeremo una versione *quantistica* del circuito a mezza scala discusso in precedenza.\n",
        "\n",
        "<span id=\"1-mapping\" />\n",
        "\n",
        "#### 1. Mappatura\n",
        "\n",
        "Il circuito sommatore classico utilizza una porta XOR e una porta AND per calcolare rispettivamente i bit di somma e di riporto. Possiamo adattare queste porte al contesto quantistico per realizzare il mezzo sommatore quantistico. Innanzitutto, ricordando che le porte quantistiche sono *reversibili*, non possiamo semplicemente sovrascrivere gli ingressi. Al contrario, introduciamo due qubit ausiliari inizializzati a $\\vert 0\\rangle$ per memorizzare la somma e il riporto. Quindi, il nostro stato quantico completo consisterà nei qubit $A$ e $B$, e nei qubit di somma e riporto, che etichetteremo $S$ e $C$ :\n",
        "\n",
        "$\\vert \\psi\\rangle = \\vert C S B A\\rangle$\n",
        "\n",
        "Ora abbiamo bisogno di porte quantistiche che realizzino ciò che le porte XOR e AND facevano nel circuito classico.\n",
        "\n",
        "**SOMMA:**\n",
        "\n",
        "Per lo XOR, applichiamo due CNOT, ciascuno con i qubit di controllo $A$ e $B$ e il qubit di destinazione $S$ per entrambi. Se $A$ e $B$ sono diversi, allora una delle porte CNOT commuta $S$ nello stato $\\vert 1\\rangle$. Se $A$ e $B$ sono entrambi $\\vert 0\\rangle$, allora non succede nulla a $S$ e rimane nello stato $\\vert 0\\rangle$. Se $A$ e $B$ sono entrambi $\\vert 1\\rangle$, allora lo stato di $S$ si capovolge due volte, riportandolo allo stato $\\vert 0\\rangle$.\n",
        "\n",
        "**Trasportare:**\n",
        "\n",
        "Per il bit di riporto, abbiamo bisogno di qualcosa che funzioni come la classica porta AND.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Ripercorrete le porte di cui abbiamo parlato per vedere se riuscite a indovinare quale porta quantistica useremo al posto della porta AND classica:\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    È la porta di Toffoli! Ricordiamo che la porta di Toffoli, o porta controllata-NOT, capovolge lo stato di destinazione se e solo se il qubit di controllo 0 E il qubit di controllo 1 sono entrambi $\\vert 1\\rangle$. Quindi, se il qubit di destinazione inizia nello stato $\\vert 0\\rangle$, ha la stessa azione della porta AND.\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Ora abbiamo tutti gli ingredienti necessari per realizzare il circuito quantistico:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "0bf14732-29fb-41c7-a4b3-94bd276ebc33",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/0bf14732-29fb-41c7-a4b3-94bd276ebc33-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# qubits: a, b, sum, carry\n",
        "qc = QuantumCircuit(4)\n",
        "\n",
        "# Choose values for A and B:\n",
        "a = 0\n",
        "b = 0\n",
        "\n",
        "# Prepare A and B qubits according to selected values:\n",
        "if a:\n",
        "    qc.x(0)\n",
        "if b:\n",
        "    qc.x(1)\n",
        "\n",
        "# XOR (sum) into qubit 2\n",
        "qc.cx(0, 2)\n",
        "qc.cx(1, 2)\n",
        "\n",
        "# AND (carry) into qubit 3\n",
        "qc.ccx(0, 1, 3)  # a AND b\n",
        "\n",
        "# measure\n",
        "qc.measure_all()\n",
        "\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "cd129de5-0b73-44db-97ea-f819184e3661",
      "metadata": {},
      "source": [
        "Qui sopra è riportato lo schema del circuito quantistico a semiconduttori. Come detto in precedenza, i fili rappresentano i qubit $0$ a $3$ ordinati dall'alto verso il basso, e il registro di bit classico è il filo inferiore a doppia linea. Poi, leggendo da sinistra a destra, vediamo come i gate vengono applicati a ciascun qubit, osservando dove appaiono le caselle sui fili corrispondenti. Infine, le misure sono mostrate alla fine. Le misurazioni fanno collassare gli stati dei qubit in valori definiti $0$ o $1$ e i risultati vengono inviati a un registro classico.\n",
        "\n",
        "Una sottigliezza: sebbene lo schema del circuito sia disegnato da sinistra a destra, quando si scrive l'espressione matriciale corrispondente bisogna leggerla da destra a sinistra. Questo perché nella moltiplicazione matriciale, l'operatore più vicino al vettore di stato agisce per primo. Quindi, ad esempio, il circuito di cui sopra (ignorando le misure) può essere scritto come:\n",
        "\n",
        "$$\n",
        "CCNOT(q_0,q_1,q_3)CNOT(q_1, q_2)CNOT(q_0,q_2)\\vert q_3 q_2 q_1 q_0\\rangle\n",
        "$$\n",
        "\n",
        "<span id=\"2-optimizing\" />\n",
        "\n",
        "#### 2. Ottimizzazione:\n",
        "\n",
        "Successivamente, dobbiamo ottimizzare il circuito per farlo funzionare sull'hardware quantistico. Questa ottimizzazione è realizzata attraverso il transpiler, che traduce il circuito astratto mostrato sopra in istruzioni comprensibili al computer quantistico. Assegna i qubit logici di cui sopra a qubit reali, fisici, sul processore e riscrive le porte in termini di un proprio insieme nativo di porte ottimizzate per funzionare sul computer quantistico. Infine, il transpiler implementa anche qualcosa chiamato \"soppressione e mitigazione degli errori\" per cercare di minimizzare l'effetto degli errori sul risultato. Questo aspetto non è così importante per il nostro circuito molto semplice, ma se proseguite nel vostro viaggio nell'informatica quantistica per eseguire circuiti più complicati, vedrete presto il valore della soppressione e della mitigazione degli errori. Se volete saperne di più, consultate il corso di Olivia Lane, [Quantum Computing in Practice](/learning/courses/quantum-computing-in-practice/introduction).\n",
        "\n",
        "Per prima cosa, si caricano i pacchetti necessari per comunicare con i computer quantistici di IBM® e si seleziona un backend su cui eseguire l'operazione. Possiamo scegliere il backend meno trafficato, oppure selezionare un backend specifico di cui conosciamo le proprietà.\n",
        "\n",
        "Di seguito è riportato un codice per salvare le credenziali al primo utilizzo. Assicurarsi di eliminare queste informazioni dal blocco note dopo averlo salvato nel proprio ambiente, in modo che le credenziali non vengano accidentalmente condivise quando si condivide il blocco note. Per ulteriori informazioni, vedere [Configurazione dell'account IBM Cloud](/docs/guides/cloud-setup) e [Inizializzazione del servizio in un ambiente non attendibile](/docs/guides/cloud-setup-untrusted).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bdc5e025-8bf4-4fbc-af80-4404e2577511",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "ibm_fez\n"
          ]
        }
      ],
      "source": [
        "# Load IBM Quantum Compute Service\n",
        "from qiskit_ibm_runtime import QiskitRuntimeService\n",
        "\n",
        "# Load IBM Quantum Compute Service\n",
        "\n",
        "# Syntax for first saving your token.  Delete these lines after saving your credentials.\n",
        "# QiskitRuntimeService.save_account(channel='ibm_quantum_platform',\n",
        "# instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)\n",
        "# service = QiskitRuntimeService(channel='ibm_quantum_platform')\n",
        "\n",
        "# Load saved credentials\n",
        "service = QiskitRuntimeService()\n",
        "\n",
        "# Use the least busy backend, or uncomment the loading of a specific backend like \"ibm_brisbane\".\n",
        "backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)\n",
        "# backend = service.backend(\"ibm_brisbane\")\n",
        "print(backend.name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "4b4fb4cb-7e4a-47f4-a5d5-803b2d513a61",
      "metadata": {},
      "source": [
        "Ora utilizziamo il transpiler per ottimizzare il circuito. Possiamo scegliere il livello di ottimizzazione da 0 (nessuna ottimizzazione) a 3 (massima ottimizzazione). Per vedere cosa comporta ciascun livello, visitate la guida ai [livelli di ottimizzazione di Set Transpiler](/docs/guides/set-optimization). Il circuito risultante sarà molto diverso dal circuito logico realizzato nella fase di mappatura.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "ad106853-7416-4fb9-b8e3-c43bb81c9059",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/ad106853-7416-4fb9-b8e3-c43bb81c9059-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Transpile the circuit and optimize for running on the quantum computer selected\n",
        "# Step 2: Transpile\n",
        "from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager\n",
        "\n",
        "target = backend.target\n",
        "pm = generate_preset_pass_manager(target=target, optimization_level=3)\n",
        "qc_isa = pm.run(qc)\n",
        "\n",
        "qc_isa.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d9c345cf-9a25-4b6f-a5ec-62a6cefe3f27",
      "metadata": {},
      "source": [
        "Un \"Sampler\" è una primitiva progettata per campionare i possibili stati risultanti da un circuito quantistico e raccogliere dati statistici su quali stati potrebbero essere misurati e con quale probabilità. Qui importiamo il Sampler \" IBM Quantum \":\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "13a3faee-256d-4038-b0bf-ef1100139a96",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the IBM Quantum primitive and session\n",
        "from qiskit_ibm_runtime import SamplerV2 as Sampler\n",
        "\n",
        "sampler = Sampler(mode=backend)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3d392a16-51ae-4367-8b75-4abf520f6474",
      "metadata": {},
      "source": [
        "Se avete esaurito il tempo a vostra disposizione sui computer quantistici reali o se non avete una connessione a Internet, potete preferire l'uso di un simulatore. A tale scopo, eseguire la cella sottostante e decommentare la riga associata nel passaggio \"Esegui\".\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "bcc1cab6-73db-4c8e-96b6-af7137ab6bd1",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Load the backend sampler\n",
        "from qiskit.primitives import BackendSamplerV2\n",
        "\n",
        "# Load the Aer simulator and generate a noise model based on the currently-selected backend.\n",
        "from qiskit_aer import AerSimulator\n",
        "from qiskit_aer.noise import NoiseModel\n",
        "\n",
        "noise_model = NoiseModel.from_backend(backend)\n",
        "\n",
        "# Define a simulator using Aer, and use it in Sampler.\n",
        "backend_sim = AerSimulator(noise_model=noise_model)\n",
        "sampler_sim = BackendSamplerV2(backend=backend_sim)\n",
        "\n",
        "# Alternatively, load a fake backend with generic properties and define a simulator.\n",
        "# backend_gen = GenericBackendV2(num_qubits=18)\n",
        "# sampler_gen = BackendSamplerV2(backend=backend_gen)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6112fb67-3f51-4532-bb30-331b687cb43d",
      "metadata": {},
      "source": [
        "<span id=\"3-executing\" />\n",
        "\n",
        "#### 3. Esecuzione\n",
        "\n",
        "Dopo aver preparato il circuito, ora possiamo farlo funzionare sul computer quantistico!\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "0609b820-bb46-4a00-b33b-813ce8843ae1",
      "metadata": {},
      "outputs": [],
      "source": [
        "job = sampler.run([qc_isa], shots=100)\n",
        "# job = sampler_sim.run([qc_isa]) # uncomment if you want to run on a simulator\n",
        "res = job.result()\n",
        "counts = res[0].data.meas.get_counts()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fea26bd9-84c9-402f-bd7e-785754993af9",
      "metadata": {},
      "source": [
        "<span id=\"4-post-processing\" />\n",
        "\n",
        "#### 4. Post-elaborazione\n",
        "\n",
        "Ora siamo pronti a visualizzare i risultati! Visualizzeremo un istogramma dei 100 campioni del circuito.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "a4efc93d-ed2e-406f-b335-deeaa661c55b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "counts =  {'0000': 90, '0100': 4, '1100': 3, '0010': 3}\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<Image src=\"/learning/images/modules/quantum-mechanics/get-started-with-qiskit/extracted-outputs/a4efc93d-ed2e-406f-b335-deeaa661c55b-1.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.visualization import plot_histogram\n",
        "\n",
        "print(\"counts = \", counts)\n",
        "plot_histogram(counts)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c228359b-7022-426a-ae7f-3599efb2231e",
      "metadata": {},
      "source": [
        "L'istogramma qui sopra mostra i risultati delle misure di tutti e quattro i qubit alla fine del circuito. Un computer quantistico ideale con zero rumore avrebbe misurato i qubit per avere sempre gli stessi valori, ma in realtà il rumore farà sì che alcune corse producano errori.\n",
        "\n",
        "<span id=\"check-your-understanding\" />\n",
        "\n",
        "#### Verifica la tua comprensione\n",
        "\n",
        "Utilizzando la stringa di bit con il maggior numero di conteggi come valori per $A$, $B$, $S$ e $C$, verificate che il circuito dell'addizionatore quantistico abbia funzionato.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    Dobbiamo verificare che $A+B = S+2 \\times C$. Ricordiamo che l'ordine delle bitstringhe segue la notazione little-endian, quindi viene letto `CSBA`.\n",
        "\n",
        "    Dall'istogramma sopra riportato, si nota che la stringa di bit `0000` è quella dominante.\n",
        "\n",
        "    $0 + 0 = 0 + 0 \\times 2 = 0 ~\\checkmark$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Tornate indietro e cambiate i valori di $A$ e $B$ in $A=1$ e $B=1$ e ripercorrete i passaggi dello schema Qiskit per eseguire nuovamente il circuito. Verificate che il circuito sommatore funzioni di nuovo.\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Risposta\">\n",
        "    Si dovrebbe ottenere un istogramma in cui la stringa di bit dominante è `1011`:\n",
        "\n",
        "    $1 + 1 = 0 + 1 \\times 2 = 2 ~\\checkmark$\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n",
        "Una delle caratteristiche aggiuntive dell'half-adder *quantistico* rispetto all'half-adder classico è che può funzionare con ingressi *quantistici*. Cioè, può \"aggiungere\" i qubit $A$ e $B$ anche se si trovano in stati di sovrapposizione. Nella sezione Domande di sfida qui sotto, vi verrà chiesto di preparare i qubit in superposizioni e di vedere cosa succede!\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ca1d1257-d741-4f46-908b-73cef6bc8fc7",
      "metadata": {},
      "source": [
        "<span id=\"conclusion\" />\n",
        "\n",
        "## Conclusione\n",
        "\n",
        "Questo modulo è stato concepito per fornire una solida comprensione dei principi di base dell'informatica quantistica, confrontandola con l'informatica classica. Abbiamo esaminato il circuito classico a semiconduttore e poi vi abbiamo mostrato come adattare il circuito per funzionare con i qubit su un computer quantistico. Ora siete pronti per esplorare gli altri moduli di Qiskit in the Classroom!\n",
        "\n",
        "<span id=\"critical-concepts\" />\n",
        "\n",
        "### Concetti fondamentali:\n",
        "\n",
        "* A differenza dei bit classici, che possono assumere solo i valori 0 e 1, i qubit possono anche trovarsi in stati di **sovrapposizione** di 0 e 1.\n",
        "* I qubit multipli possono essere in una sovrapposizione sulle stringhe di bit classicamente consentite, chiamate **stati base computazionali**.\n",
        "* Più qubit possono essere **entangled** in modo che lo stato di uno dipenda dallo stato dell'altro.\n",
        "* La convenzione di Qiskit prevede l'uso della **notazione little-endian**, che pone il qubit meno significativo, $q_0$, nella posizione più a destra e il qubit più significativo, $q_N$, nella posizione più a sinistra.\n",
        "* Le **porte quantistiche** sono operazioni reversibili rappresentate da matrici unitarie che agiscono sui vettori di stato quantistici. In questa notazione, la matrice più vicina al vettore (che è più a destra) agisce per prima.\n",
        "* **Le misure** fanno collassare uno stato di sovrapposizione quantistica in uno dei suoi stati classicamente consentiti, con una probabilità pari al quadrato dell'ampiezza dello stato base computazionale corrispondente nella sovrapposizione.\n",
        "* I circuiti quantistici sono spesso rappresentati con **diagrammi di circuiti quantistici**, in cui i qubit sono rappresentati come fili orizzontali e le porte quantistiche appaiono lungo questi fili da sinistra a destra.\n",
        "* Per eseguire un circuito quantistico, utilizziamo le quattro fasi del flusso di lavoro dei **modelli Qiskit** : **Map**, **Optimize**, **Execute**, **Post-process**.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "34ccee8d-e9cc-45eb-ab30-8e8160ec9a5b",
      "metadata": {},
      "source": [
        "<span id=\"questions\" />\n",
        "\n",
        "## Domande\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "37265ba8-dc01-4aae-941f-6e051c62d7cc",
      "metadata": {},
      "source": [
        "<span id=\"true/false-questions\" />\n",
        "\n",
        "### Domande vero/falso\n",
        "\n",
        "1. In un computer classico, un singolo bit può contenere solo il valore 0 o 1.\n",
        "\n",
        "2. Entanglement significa che lo stato di un qubit è indipendente dallo stato di un altro.\n",
        "\n",
        "3. Le porte quantistiche sono generalmente operazioni irreversibili.\n",
        "\n",
        "4. La convenzione Qiskit pone il qubit meno significativo, $q_0$, nella posizione più a sinistra.\n",
        "\n",
        "5. La misurazione di uno stato quantistico dà sempre lo stesso identico risultato se ripetuta più volte.\n",
        "\n",
        "6. Il gate di Hadamard crea una sovrapposizione in un singolo qubit.\n",
        "\n",
        "7. I circuiti quantistici possono includere operazioni di misura che fanno collassare lo stato di sovrapposizione in uno degli stati classicamente consentiti.\n",
        "\n",
        "8. Il numero di possibili stati classici per $N$ bit è $2N$.\n",
        "\n",
        "9. Le probabilità di esito delle misure quantistiche sono date dalle ampiezze al quadrato degli stati base misurabili classicamente.\n",
        "\n",
        "<span id=\"short-answer-questions\" />\n",
        "\n",
        "### Domande a risposta breve\n",
        "\n",
        "1. Quali sono le principali differenze tra un bit e un qubit?\n",
        "\n",
        "2. Cosa succede a uno stato quantistico quando viene misurato?\n",
        "\n",
        "3. Perché in Qiskit si usa la notazione little-endian?\n",
        "\n",
        "4. Quali sono le quattro fasi del flusso di lavoro dei modelli Qiskit?\n",
        "\n",
        "<span id=\"challenge-questions\" />\n",
        "\n",
        "### Domande di verifica:\n",
        "\n",
        "1. Nel modulo, abbiamo usato l'addizionatore solo per aggiungere gli stati classicamente ammessi per $A$ e $B$. Ma possiamo anche preparare $A$ e $B$ in sovrapposizione! Modificare il codice per preparare ogni qubit in una sovrapposizione uguale di 0 e 1, quindi eseguire il nuovo circuito e ottenere un nuovo istogramma. Cosa vedi? Spiegare cosa sta succedendo.\n",
        "\n",
        "2. Decomposizione della porta di Toffoli. Usate `decompose()` per mostrare come la porta di Toffoli sia decomposta in porte a uno e due qubit, quindi verificate questa costruzione con la moltiplicazione matriciale. Tenete presente che, sebbene gli schemi dei circuiti si leggano da sinistra a destra, le matrici si applicano agli stati quantistici da destra a sinistra!\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "in_page_toc_max_heading_level": 2,
    "in_page_toc_min_heading_level": 2,
    "kernelspec": {
      "display_name": "Python 3",
      "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"
    },
    "widgets": {
      "application/vnd.jupyter.widget-state+json": {
        "state": {},
        "version_major": 2,
        "version_minor": 0
      }
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}