{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b88d9242-a6f2-47b6-8e0a-daf60d0c4374",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"La classe Operator\"\n",
        "description: \"Spiegazione approfondita dell'utilizzo della classe Operator in Qiskit.\"\n",
        "---\n",
        "\n",
        "<span id=\"the-operator-class\" />\n",
        "\n",
        "# La classe Operator\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9a7539be-eb3f-4a29-8a76-ea9c93559142",
      "metadata": {
        "tags": [
          "version-info"
        ]
      },
      "source": [
        "{/*\n",
        "  DO NOT EDIT THIS CELL!!!\n",
        "  This cell's content is generated automatically by a script. Anything you add\n",
        "  here will be removed next time the notebook is run. To add new content, create\n",
        "  a new cell before or after this one.\n",
        "  */}\n",
        "\n",
        "<Accordion>\n",
        "  <AccordionItem title=\"Versioni del pacchetto\">\n",
        "    Il codice di questa pagina è stato sviluppato in base ai seguenti requisiti.\n",
        "    Si consiglia di utilizzare queste versioni o versioni più recenti.\n",
        "\n",
        "    ```\n",
        "    qiskit[all]~=2.5.2\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "eb4d8e3f-5efb-4223-a15b-d6ef541370dc",
      "metadata": {},
      "source": [
        "Questa pagina spiega come utilizzare la [`Operator`](/docs/api/qiskit/qiskit.quantum_info.Operator) classe. Per una panoramica generale sulle rappresentazioni degli operatori in Qiskit, tra cui la `Operator` classe e altre, consultare [la sezione Panoramica delle classi di operatori](/docs/guides/operators-overview).\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "549bc166-9c0e-4e89-b7e2-8adafd7110c3",
      "metadata": {},
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "from qiskit.circuit import QuantumCircuit\n",
        "from qiskit.circuit.library import CXGate, RXGate, XGate\n",
        "from qiskit.quantum_info import Operator, Pauli, process_fidelity"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8292bbef-0a61-44db-a096-cee8c9b23827",
      "metadata": {},
      "source": [
        "<span id=\"convert-classes-to-operators\" />\n",
        "\n",
        "## Converti classi in operatori\n",
        "\n",
        "Molte altre classi di Qiskit possono essere convertite direttamente in un oggetto `Operator` utilizzando il metodo di inizializzazione dell'operatore. Ad esempio:\n",
        "\n",
        "* `Pauli` oggetti\n",
        "* `Gate` e gli oggetti di `Instruction`\n",
        "* `QuantumCircuit` oggetti\n",
        "\n",
        "Si noti che l'ultimo punto significa che si può usare la classe `Operator` come simulatore unitario per calcolare la matrice unitaria finale di un circuito quantistico, senza dover chiamare un backend simulatore. Se il circuito contiene operazioni non supportate, viene sollevata un'eccezione. Le operazioni non supportate sono: misura, reset, operazioni condizionali o un gate che non ha una definizione di matrice o una decomposizione in termini di gate con definizioni di matrice.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "cb6e9d7a-8dc9-4b32-81f0-278d2e7e64b5",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],\n",
            "          [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],\n",
            "          [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j],\n",
            "          [1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],\n",
            "         input_dims=(2, 2), output_dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "# Create an Operator from a Pauli object\n",
        "\n",
        "pauliXX = Pauli(\"XX\")\n",
        "Operator(pauliXX)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "ffdda3ff-75ca-486c-8e52-be80244b969f",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
            "          [0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],\n",
            "          [0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j],\n",
            "          [0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]],\n",
            "         input_dims=(2, 2), output_dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "# Create an Operator for a Gate object\n",
        "Operator(CXGate())"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "b8cbc1d9-4957-4b2d-b59c-32c1efbfbeed",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[0.70710678+0.j        , 0.        -0.70710678j],\n",
            "          [0.        -0.70710678j, 0.70710678+0.j        ]],\n",
            "         input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "# Create an operator from a parameterized Gate object\n",
        "Operator(RXGate(np.pi / 2))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "e60c3079-84bf-40cd-ace7-bae419118c99",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[ 0.70710678+0.j,  0.70710678+0.j,  0.        +0.j, ...,\n",
            "            0.        +0.j,  0.        +0.j,  0.        +0.j],\n",
            "          [ 0.        +0.j,  0.        +0.j,  0.70710678+0.j, ...,\n",
            "            0.        +0.j,  0.        +0.j,  0.        +0.j],\n",
            "          [ 0.        +0.j,  0.        +0.j,  0.        +0.j, ...,\n",
            "            0.        +0.j,  0.        +0.j,  0.        +0.j],\n",
            "          ...,\n",
            "          [ 0.        +0.j,  0.        +0.j,  0.        +0.j, ...,\n",
            "            0.        +0.j,  0.        +0.j,  0.        +0.j],\n",
            "          [ 0.        +0.j,  0.        +0.j,  0.70710678+0.j, ...,\n",
            "            0.        +0.j,  0.        +0.j,  0.        +0.j],\n",
            "          [ 0.70710678+0.j, -0.70710678+0.j,  0.        +0.j, ...,\n",
            "            0.        +0.j,  0.        +0.j,  0.        +0.j]],\n",
            "         input_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2), output_dims=(2, 2, 2, 2, 2, 2, 2, 2, 2, 2))\n"
          ]
        }
      ],
      "source": [
        "# Create an operator from a QuantumCircuit object\n",
        "circ = QuantumCircuit(10)\n",
        "circ.h(0)\n",
        "for j in range(1, 10):\n",
        "    circ.cx(j - 1, j)\n",
        "\n",
        "# Convert circuit to an operator by implicit unitary simulation\n",
        "Operator(circ)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "693e4885-bd79-4a2f-8e2b-8e4d81892c05",
      "metadata": {},
      "source": [
        "<span id=\"use-operators-in-circuits\" />\n",
        "\n",
        "## Utilizzo degli operatori nei circuiti\n",
        "\n",
        "Unitario `Operators` può essere inserito direttamente in un `QuantumCircuit` utilizzando il metodo `QuantumCircuit.append` . Questo converte `Operator` in un oggetto `UnitaryGate` , che viene aggiunto al circuito.\n",
        "\n",
        "Se l'operatore non è unitario, viene sollevata un'eccezione. Questo può essere verificato con la funzione `Operator.is_unitary()` , che restituisce `True` se l'operatore è unitario e `False` altrimenti.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "223c07c9-1b1d-4a33-a397-091cac2ec9e3",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/operator-class/extracted-outputs/223c07c9-1b1d-4a33-a397-091cac2ec9e3-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Create an operator\n",
        "XX = Operator(Pauli(\"XX\"))\n",
        "\n",
        "# Add to a circuit\n",
        "circ = QuantumCircuit(2, 2)\n",
        "circ.append(XX, [0, 1])\n",
        "circ.measure([0, 1], [0, 1])\n",
        "circ.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "04a90485-7b03-4ae3-a37d-0ae87feee6a4",
      "metadata": {},
      "source": [
        "Si noti che nell'esempio precedente l'operatore viene inizializzato da un oggetto `Pauli` . Tuttavia, l'oggetto `Pauli` può anche essere inserito direttamente nel circuito stesso e sarà convertito in una sequenza di porte Pauli a singolo qubit:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "85f37f4a-078e-401f-b222-ec230da6ae78",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "     ┌────────────┐┌─┐   \n",
              "q_0: ┤0           ├┤M├───\n",
              "     │  Pauli(XX) │└╥┘┌─┐\n",
              "q_1: ┤1           ├─╫─┤M├\n",
              "     └────────────┘ ║ └╥┘\n",
              "c: 2/═══════════════╩══╩═\n",
              "                    0  1 "
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# Add to a circuit\n",
        "circ2 = QuantumCircuit(2, 2)\n",
        "circ2.append(Pauli(\"XX\"), [0, 1])\n",
        "circ2.measure([0, 1], [0, 1])\n",
        "circ2.draw()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "59bf4972-731f-40c4-9d26-ca0110827cdc",
      "metadata": {},
      "source": [
        "<span id=\"combine-operators\" />\n",
        "\n",
        "## Operatori combinatori\n",
        "\n",
        "Gli operatori possono essere combinati con diversi metodi.\n",
        "\n",
        "<span id=\"tensor-product\" />\n",
        "\n",
        "### Prodotto tensoriale\n",
        "\n",
        "Due operatori $A$ e $B$ possono essere combinati in un operatore prodotto tensoriale $A\\otimes B$ utilizzando la funzione `Operator.tensor` . Si noti che se sia $A$ che $B$ sono operatori a singolo-qubit, allora `A.tensor(B)` = $A\\otimes B$ avrà i sottosistemi indicizzati come la matrice $B$ sul sottosistema 0 e la matrice $A$ sul sottosistema 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "0fcf1f68-8af1-417f-b6c3-313846ec5b0d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[ 0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j],\n",
            "          [ 0.+0.j, -0.+0.j,  0.+0.j, -1.+0.j],\n",
            "          [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],\n",
            "          [ 0.+0.j, -1.+0.j,  0.+0.j, -0.+0.j]],\n",
            "         input_dims=(2, 2), output_dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "A = Operator(Pauli(\"X\"))\n",
        "B = Operator(Pauli(\"Z\"))\n",
        "A.tensor(B)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "bca7c8a7-5f19-405c-9f27-3e75db53cb5e",
      "metadata": {},
      "source": [
        "<span id=\"tensor-expansion\" />\n",
        "\n",
        "### Espansione tensoriale\n",
        "\n",
        "Un'operazione strettamente correlata è `Operator.expand`, che agisce come un prodotto tensoriale ma in ordine inverso. Quindi, per due operatori $A$ e $B$ si ha `A.expand(B)` = $B\\otimes A$ dove i sottosistemi sono indicizzati come la matrice $A$ sul sottosistema 0 e la matrice $B$ sul sottosistema 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "a38a8588-f0a5-4533-95dc-23ff383501d6",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[ 0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j],\n",
            "          [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j],\n",
            "          [ 0.+0.j,  0.+0.j, -0.+0.j, -1.+0.j],\n",
            "          [ 0.+0.j,  0.+0.j, -1.+0.j, -0.+0.j]],\n",
            "         input_dims=(2, 2), output_dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "A = Operator(Pauli(\"X\"))\n",
        "B = Operator(Pauli(\"Z\"))\n",
        "A.expand(B)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6a33cf17-68f8-442d-b4e0-6b899d1d280a",
      "metadata": {},
      "source": [
        "<span id=\"composition\" />\n",
        "\n",
        "### Composizione\n",
        "\n",
        "È anche possibile comporre due operatori $A$ e $B$ per implementare la moltiplicazione di matrici con il metodo `Operator.compose` . `A.compose(B)` restituisce l'operatore con la matrice $B.A$ :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "a45e1ef6-09b4-4d70-a9e2-0eb5f1b59a83",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[ 0.+0.j,  1.+0.j],\n",
            "          [-1.+0.j,  0.+0.j]],\n",
            "         input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "A = Operator(Pauli(\"X\"))\n",
        "B = Operator(Pauli(\"Z\"))\n",
        "A.compose(B)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f54c6b4e-e8ac-4ae7-ac02-60300a46c88c",
      "metadata": {},
      "source": [
        "Si può anche comporre in ordine inverso applicando $B$ davanti a $A$ usando il kwarg `front` di `compose`: `A.compose(B, front=True)` = $A.B$ :\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "30b6a60d-11fd-4b19-a673-790aab891554",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[ 0.+0.j, -1.+0.j],\n",
            "          [ 1.+0.j,  0.+0.j]],\n",
            "         input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "A = Operator(Pauli(\"X\"))\n",
        "B = Operator(Pauli(\"Z\"))\n",
        "A.compose(B, front=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f08c91f5-88f0-408f-ae9e-03cec65de305",
      "metadata": {},
      "source": [
        "<span id=\"subsystem-composition\" />\n",
        "\n",
        "### Composizione del sottosistema\n",
        "\n",
        "Si noti che la precedente composizione richiede che la dimensione totale di uscita del primo operatore $A$ sia uguale alla dimensione totale di ingresso dell'operatore composto $B$ (e analogamente, la dimensione di uscita di $B$ deve essere uguale alla dimensione di ingresso di $A$ quando si compone con `front=True`).\n",
        "\n",
        "Si può anche comporre un operatore più piccolo con una selezione di sottosistemi su un operatore più grande, utilizzando il kwarg `qargs` di `compose`, con o senza `front=True`. In questo caso, le dimensioni di ingresso e di uscita dei sottosistemi composti devono corrispondere. \\*Si noti che l'operatore più piccolo deve essere sempre l'argomento dell' \\*`compose` *metodo.*\n",
        "\n",
        "Ad esempio, per comporre un gate a due-qubit con un operatore a tre-qubit:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "e604f408-3ec3-49fa-830a-eaf960fdd40d",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[ 0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j,\n",
            "            0.+0.j],\n",
            "          [ 0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j, -1.+0.j,  0.+0.j,\n",
            "            0.+0.j],\n",
            "          [ 0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  1.+0.j,\n",
            "            0.+0.j],\n",
            "          [ 0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,\n",
            "           -1.+0.j],\n",
            "          [ 1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,\n",
            "            0.+0.j],\n",
            "          [ 0.+0.j, -1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,\n",
            "            0.+0.j],\n",
            "          [ 0.+0.j,  0.+0.j,  1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,\n",
            "            0.+0.j],\n",
            "          [ 0.+0.j,  0.+0.j,  0.+0.j, -1.+0.j,  0.+0.j,  0.+0.j,  0.+0.j,\n",
            "            0.+0.j]],\n",
            "         input_dims=(2, 2, 2), output_dims=(2, 2, 2))\n"
          ]
        }
      ],
      "source": [
        "# Compose XZ with a 3-qubit identity operator\n",
        "op = Operator(np.eye(2**3))\n",
        "XZ = Operator(Pauli(\"XZ\"))\n",
        "op.compose(XZ, qargs=[0, 2])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "d2024a14-891b-46e4-93e7-4dc73e33e928",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j],\n",
            "          [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
            "          [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j],\n",
            "          [0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.-1.j, 0.+0.j],\n",
            "          [0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
            "          [0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
            "          [0.+0.j, 0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],\n",
            "          [0.+0.j, 0.+0.j, 0.+1.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j]],\n",
            "         input_dims=(2, 2, 2), output_dims=(2, 2, 2))\n"
          ]
        }
      ],
      "source": [
        "# Compose YX in front of the previous operator\n",
        "op = Operator(np.eye(2**3))\n",
        "YX = Operator(Pauli(\"YX\"))\n",
        "op.compose(YX, qargs=[0, 2], front=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5e362de3-866d-42b3-8d3c-a3905d9d4005",
      "metadata": {},
      "source": [
        "<span id=\"linear-combinations\" />\n",
        "\n",
        "### Combinazioni lineari\n",
        "\n",
        "Gli operatori possono anche essere combinati utilizzando gli operatori lineari standard per l'addizione, la sottrazione e la moltiplicazione scalare per numeri complessi.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "79b9ccd5-a002-4499-9439-7c553177abb8",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[-1.5+0.j,  0. +0.j,  0. +0.j,  0. +0.j],\n",
            "          [ 0. +0.j,  1.5+0.j,  1. +0.j,  0. +0.j],\n",
            "          [ 0. +0.j,  1. +0.j,  1.5+0.j,  0. +0.j],\n",
            "          [ 0. +0.j,  0. +0.j,  0. +0.j, -1.5+0.j]],\n",
            "         input_dims=(2, 2), output_dims=(2, 2))\n"
          ]
        }
      ],
      "source": [
        "XX = Operator(Pauli(\"XX\"))\n",
        "YY = Operator(Pauli(\"YY\"))\n",
        "ZZ = Operator(Pauli(\"ZZ\"))\n",
        "\n",
        "op = 0.5 * (XX + YY - 3 * ZZ)\n",
        "op"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "235d9549-a7f6-4c8c-8592-de57e5e45fc6",
      "metadata": {},
      "source": [
        "Un punto importante è che mentre `tensor`, `expand`, e `compose` preservano l'unitarietà degli operatori unitari, le combinazioni lineari non lo fanno; quindi, sommando due operatori unitari si otterrà, in generale, un operatore non unitario:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "97615df2-f6dc-4367-8463-f5c0c1ef94eb",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "False"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "op.is_unitary()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "1a2bf1cd-6f0f-446f-a993-ae9c2d22984e",
      "metadata": {},
      "source": [
        "<span id=\"implicit-conversion-to-operators\" />\n",
        "\n",
        "### Conversione implicita in operatori\n",
        "\n",
        "Si noti che per tutti i metodi seguenti, se il secondo oggetto non è già un oggetto `Operator` , viene implicitamente convertito in uno di essi dal metodo. Ciò significa che le matrici possono essere passate direttamente senza essere prima convertite esplicitamente in `Operator` . Se la conversione non è possibile, viene sollevata un'eccezione.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "9d72e40f-8d72-4cd7-8350-1896e88528c0",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Operator([[0.+0.j, 1.+0.j],\n",
            "          [1.+0.j, 0.+0.j]],\n",
            "         input_dims=(2,), output_dims=(2,))\n"
          ]
        }
      ],
      "source": [
        "# Compose with a matrix passed as a list\n",
        "Operator(np.eye(2)).compose([[0, 1], [1, 0]])"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "0ee93f02-c3ea-44b0-8b87-f79e3107749e",
      "metadata": {},
      "source": [
        "<span id=\"compare-operators\" />\n",
        "\n",
        "## Confronta operatori\n",
        "\n",
        "Gli operatori implementano un metodo di uguaglianza che può essere utilizzato per verificare se due operatori sono approssimativamente uguali.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "ce9983d1-e20a-432d-af22-d6a1011f412c",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "True"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "Operator(Pauli(\"X\")) == Operator(XGate())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "36bbbbf9-3ed7-4aab-bc9e-f542325372f1",
      "metadata": {},
      "source": [
        "Si noti che in questo modo si verifica che ogni elemento della matrice degli operatori sia approssimativamente uguale; due unitari che differiscono di una fase globale non sono considerati uguali:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "a42ba8a1-5ab5-44d0-bd54-4147f4f28e53",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "False"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "Operator(XGate()) == np.exp(1j * 0.5) * Operator(XGate())"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c06612c0-be6e-41b5-9ba5-92a9d7755c2f",
      "metadata": {},
      "source": [
        "<span id=\"process-fidelity\" />\n",
        "\n",
        "### Fedeltà del processo\n",
        "\n",
        "È inoltre possibile confrontare gli operatori utilizzando la funzione `process_fidelity` del modulo *Informazione quantistica*. Si tratta di una quantità teorica dell'informazione che indica la vicinanza tra due canali quantistici e che, nel caso degli operatori unitari, non dipende dalla fase globale.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "813d97d1-94d3-4c65-aca0-324b09cebc6a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Process fidelity = 1.0\n"
          ]
        }
      ],
      "source": [
        "# Two operators which differ only by phase\n",
        "op_a = Operator(XGate())\n",
        "op_b = np.exp(1j * 0.5) * Operator(XGate())\n",
        "\n",
        "# Compute process fidelity\n",
        "F = process_fidelity(op_a, op_b)\n",
        "print(\"Process fidelity =\", F)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "993bab6d-7f37-4363-a17e-8b8e3b7de30a",
      "metadata": {},
      "source": [
        "Si noti che la fedeltà del processo è generalmente una misura valida di vicinanza solo se gli operatori in ingresso sono unitari (o CP nel caso di canali quantistici), e viene sollevata un'eccezione se gli ingressi non sono CP.\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "52ef24af-888c-4c76-ab6f-4e1e8323cf2a",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Esplorare il riferimento all' [API dell'operatore](/docs/api/qiskit/qiskit.quantum_info.Operator#operator).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "anaconda-cloud": {},
    "celltoolbar": "Tags",
    "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"
    },
    "varInspector": {
      "cols": {
        "lenName": 16,
        "lenType": 16,
        "lenVar": 40
      },
      "kernels_config": {
        "python": {
          "delete_cmd_postfix": "",
          "delete_cmd_prefix": "del ",
          "library": "var_list.py",
          "varRefreshCmd": "print(var_dic_list())"
        },
        "r": {
          "delete_cmd_postfix": ") ",
          "delete_cmd_prefix": "rm(",
          "library": "var_list.r",
          "varRefreshCmd": "cat(var_dic_list()) "
        }
      },
      "types_to_exclude": [
        "module",
        "function",
        "builtin_function_or_method",
        "instance",
        "_Feature"
      ],
      "window_display": false
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}