{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "72a56be1-db57-4364-acf3-57814453b64e",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Feedforward classico e flusso di controllo (circuiti dinamici)\"\n",
        "description: \"Utilizza Qiskit per il feedforward classico e il flusso di controllo, altrimenti denominati circuiti dinamici\"\n",
        "---\n",
        "\n",
        "<span id=\"classical-feedforward-and-control-flow-dynamic-circuits\" />\n",
        "\n",
        "# Feedforward classico e flusso di controllo (circuiti dinamici)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7f636096-9a03-4f72-823b-4b9219d496f0",
      "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.1\n",
        "    ```\n",
        "  </AccordionItem>\n",
        "</Accordion>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ea7e102f-6e41-4bdd-95be-5dd13225952b",
      "metadata": {},
      "source": [
        "I circuiti dinamici sono strumenti potenti con i quali è possibile misurare i qubit nel mezzo dell'esecuzione di un circuito quantistico e quindi eseguire operazioni logiche classiche all'interno del circuito, sulla base del risultato di tali misurazioni a metà circuito.  Questo processo è noto anche come *feedforward classico*. Sebbene sia ancora presto per capire come sfruttare al meglio i circuiti dinamici, la comunità di ricerca quantistica ha già identificato una serie di casi d'uso, come i seguenti:\n",
        "\n",
        "* Preparazione efficiente dello stato quantistico, come [lo stato GHZ](https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.030339), [lo stato W](https://arxiv.org/abs/2403.07604) (per ulteriori informazioni sullo stato W, consultare anche [\"Preparazione dello stato mediante circuiti superficiali che utilizzano feed forward\"](https://arxiv.org/abs/2307.14840) ) e un'ampia classe di [stati di prodotto matriciale](https://arxiv.org/abs/2404.16083)\n",
        "* [Efficiente entanglement a lungo raggio](https://journals.aps.org/prxquantum/abstract/10.1103/PRXQuantum.5.030339) tra qubit sullo stesso chip utilizzando circuiti poco profondi\n",
        "* [Campionamento efficiente di circuiti simili a IQP](https://arxiv.org/pdf/2505.04705)\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b2953dd4-218e-4daa-a753-0d2aa5e0a0bb",
      "metadata": {},
      "source": [
        "Qiskit supporta quattro costrutti di flusso di controllo per il feedforward classico, ciascuno implementato come metodo su [`QuantumCircuit`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit). I costrutti e i relativi metodi sono:\n",
        "\n",
        "* Istruzione if - [`QuantumCircuit.if_test`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#if_test)\n",
        "* Istruzione switch - [`QuantumCircuit.switch`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#switch)\n",
        "* Ciclo \"for\" - [`QuantumCircuit.for_loop`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#for_loop)\n",
        "* Ciclo while - [`QuantumCircuit.while_loop`](/docs/api/qiskit/qiskit.circuit.QuantumCircuit#while_loop)\n",
        "\n",
        "Ciascuno di questi metodi restituisce un [gestore di contesto](https://docs.python.org/3/reference/datamodel.html#with-statement-context-managers) e viene solitamente utilizzato in un’istruzione `with` . Il resto di questa guida illustra ciascuno di questi costrutti e come utilizzarli.\n",
        "\n",
        "<Admonition type=\"caution\">\n",
        "  Esistono alcune limitazioni relative alle operazioni classiche di feedforward e di controllo del flusso sull'hardware quantistico che potrebbero influire sul vostro programma. Per ulteriori informazioni, consultare [la sezione \"Esecuzione di circuiti dinamici\"](/docs/guides/execute-dynamic-circuits).\n",
        "</Admonition>\n",
        "\n",
        "<span id=\"if-statement\" />\n",
        "\n",
        "## `if` istruzione\n",
        "\n",
        "L'istruzione `if` viene utilizzata per eseguire operazioni condizionali basate sul valore di un bit o di un registro classico.\n",
        "\n",
        "Nell'esempio che segue, applichiamo un gate di Hadamard a un qubit e lo misuriamo. Se il risultato è 1, allora applichiamo un gate X sul qubit, che ha l'effetto di riportarlo allo stato 0. Poi misuriamo di nuovo il qubit. Il risultato della misurazione deve essere 0 con una probabilità del 100%.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "f0f191a7-d59d-415f-a11b-9f39e431269b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/f0f191a7-d59d-415f-a11b-9f39e431269b-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 1,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "\n",
        "qubits = QuantumRegister(1)\n",
        "clbits = ClassicalRegister(1)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "(q0,) = qubits\n",
        "(c0,) = clbits\n",
        "\n",
        "circuit.h(q0)\n",
        "circuit.measure(q0, c0)\n",
        "with circuit.if_test((c0, 1)):\n",
        "    circuit.x(q0)\n",
        "circuit.measure(q0, c0)\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'0': 1024}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "867d8f76-9cba-47fd-a341-ac40db6ee073",
      "metadata": {},
      "source": [
        "All'istruzione `with` può essere assegnato un target di assegnazione che è a sua volta un gestore di contesto che può essere memorizzato e successivamente utilizzato per creare un blocco else, che viene eseguito ogni volta che il contenuto del blocco `if` *non* viene eseguito.\n",
        "\n",
        "Nell'esempio che segue, inizializziamo i registri con due qubit e due bit classici. Applichiamo un gate di Hadamard al primo qubit e lo misuriamo. Se il risultato è 1, si applica un gate Hadamard al secondo qubit; altrimenti, si applica un gate X al secondo qubit. Infine, misuriamo anche il secondo qubit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "d40249f1-d951-49e4-9ee9-662d3568f32f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/d40249f1-d951-49e4-9ee9-662d3568f32f-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 2,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qubits = QuantumRegister(2)\n",
        "clbits = ClassicalRegister(2)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "(q0, q1) = qubits\n",
        "(c0, c1) = clbits\n",
        "\n",
        "circuit.h(q0)\n",
        "circuit.measure(q0, c0)\n",
        "with circuit.if_test((c0, 1)) as else_:\n",
        "    circuit.h(q1)\n",
        "with else_:\n",
        "    circuit.x(q1)\n",
        "circuit.measure(q1, c1)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'01': 260, '11': 272, '10': 492}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ba7b688a-e961-4361-9edf-47b387704f9d",
      "metadata": {},
      "source": [
        "Oltre al condizionamento su un singolo bit classico, è anche possibile condizionare sul valore di un registro classico composto da più bit.\n",
        "\n",
        "Nell'esempio seguente, applichiamo i gate di Hadamard a due qubit e li misuriamo. Se il risultato è `01`, ovvero il primo qubit è 1 e il secondo qubit è 0, allora applichiamo un gate X a un terzo qubit. Infine, misuriamo il terzo qubit. Si noti che, per chiarezza, abbiamo scelto di specificare lo stato del terzo bit classico, che è 0, nella `if` condizione. Nel disegno del circuito, la condizione è indicata dai cerchi sui bit classici che vengono condizionati. Un cerchio pieno indica il condizionamento su 1, mentre un cerchio tratteggiato indica il condizionamento su 0.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "id": "6ccfd81b-0bda-409e-bd9a-116848df631b",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/6ccfd81b-0bda-409e-bd9a-116848df631b-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qubits = QuantumRegister(3)\n",
        "clbits = ClassicalRegister(3)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "(q0, q1, q2) = qubits\n",
        "(c0, c1, c2) = clbits\n",
        "\n",
        "circuit.h([q0, q1])\n",
        "circuit.measure(q0, c0)\n",
        "circuit.measure(q1, c1)\n",
        "with circuit.if_test((clbits, 0b001)):\n",
        "    circuit.x(q2)\n",
        "circuit.measure(q2, c2)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'101': 269, '011': 260, '000': 252, '010': 243}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f85c34ed-bca6-40b9-9db2-e534f8c79010",
      "metadata": {},
      "source": [
        "<span id=\"switch-statement\" />\n",
        "\n",
        "## Istruzione switch\n",
        "\n",
        "L'istruzione switch viene utilizzata per selezionare delle azioni in base al valore di un bit o di un registro classico. È simile a un'istruzione \"if\", ma permette di specificare più casi per la logica di ramificazione. L'esempio riportato di seguito applica una porta di Hadamard a un qubit e ne rileva il valore. Se il risultato è 0, applicare un gate X al qubit; se il risultato è 1, applicare un gate Z. Il risultato della misurazione dovrebbe essere 1 con una probabilità del 100%.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "04b82e33-7c95-4042-a5e9-d00ff075ca02",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/04b82e33-7c95-4042-a5e9-d00ff075ca02-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qubits = QuantumRegister(1)\n",
        "clbits = ClassicalRegister(1)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "(q0,) = qubits\n",
        "(c0,) = clbits\n",
        "\n",
        "circuit.h(q0)\n",
        "circuit.measure(q0, c0)\n",
        "with circuit.switch(c0) as case:\n",
        "    with case(0):\n",
        "        circuit.x(q0)\n",
        "    with case(1):\n",
        "        circuit.z(q0)\n",
        "circuit.measure(q0, c0)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'1': 1024}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e0da6aa3-736e-4eb5-ad36-8626236f7604",
      "metadata": {},
      "source": [
        "Poiché nell'esempio precedente è stato utilizzato un singolo bit classico, i casi possibili erano solo due; pertanto, si sarebbe potuto ottenere lo stesso risultato utilizzando un'istruzione if-else. Il caso dello switch è utile soprattutto quando si effettua una ramificazione in base al valore di un registro classico composto da più bit. L'esempio seguente mostra come definire un caso predefinito, che viene eseguito se nessuno dei casi precedenti viene eseguito. Si noti che in un'istruzione switch viene eseguito sempre e solo uno dei blocchi. Non c'è alcun \"fallthrough\".\n",
        "\n",
        "L'esempio riportato di seguito applica le porte di Hadamard a due qubit e ne misura i valori. Se il risultato è 00 o 11, applicare un gate Z al terzo qubit. Se il risultato è 01, applicare una porta Y. Se nessuno dei casi precedenti corrisponde, applicare un gate X. Infine, misurare il terzo qubit.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "6aaba57e-7841-47d3-8f31-f922cb2b81f7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/6aaba57e-7841-47d3-8f31-f922cb2b81f7-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qubits = QuantumRegister(3)\n",
        "clbits = ClassicalRegister(3)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "(q0, q1, q2) = qubits\n",
        "(c0, c1, c2) = clbits\n",
        "\n",
        "circuit.h([q0, q1])\n",
        "circuit.measure(q0, c0)\n",
        "circuit.measure(q1, c1)\n",
        "with circuit.switch(clbits) as case:\n",
        "    with case(0b000, 0b011):\n",
        "        circuit.z(q2)\n",
        "    with case(0b001):\n",
        "        circuit.y(q2)\n",
        "    with case(case.DEFAULT):\n",
        "        circuit.x(q2)\n",
        "circuit.measure(q2, c2)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'101': 267, '110': 249, '011': 265, '000': 243}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e5f1da75-abcc-42de-8aa6-6f2a6d450ddd",
      "metadata": {},
      "source": [
        "<span id=\"for-loop\" />\n",
        "\n",
        "## Per il ciclo\n",
        "\n",
        "Un ciclo \"for\" viene utilizzato per scorrere una sequenza di valori classici ed eseguire alcune operazioni durante ogni iterazione.\n",
        "\n",
        "L'esempio seguente utilizza un ciclo for per applicare 5 porte X a un qubit e poi ne misura il valore. Poiché esegue un numero dispari di porte X, l'effetto complessivo è quello di far passare il qubit dallo stato 0 allo stato 1.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "c6c91715-7a98-46a8-885e-92d3d1f99557",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/c6c91715-7a98-46a8-885e-92d3d1f99557-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qubits = QuantumRegister(1)\n",
        "clbits = ClassicalRegister(1)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "(q0,) = qubits\n",
        "(c0,) = clbits\n",
        "\n",
        "with circuit.for_loop(range(5)) as _:\n",
        "    circuit.x(q0)\n",
        "circuit.measure(q0, c0)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'1': 1024}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "98e7b4f3-e73e-4caf-9326-11b45bd6cfcf",
      "metadata": {},
      "source": [
        "<span id=\"while-loop\" />\n",
        "\n",
        "## Loop While\n",
        "\n",
        "Un ciclo while viene utilizzato per ripetere una serie di istruzioni finché una determinata condizione rimane vera.\n",
        "\n",
        "L'esempio riportato di seguito applica le porte di Hadamard a due qubit e ne misura i valori. Quindi crea un ciclo while che ripete questa procedura finché il risultato della misurazione è 11. Di conseguenza, il risultato finale non dovrebbe mai essere 11, mentre le altre possibilità dovrebbero presentarsi con frequenza approssimativamente uguale.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "id": "c26465ff-5d3e-4799-8c68-c327abff5694",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/c26465ff-5d3e-4799-8c68-c327abff5694-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 7,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qubits = QuantumRegister(2)\n",
        "clbits = ClassicalRegister(2)\n",
        "circuit = QuantumCircuit(qubits, clbits)\n",
        "\n",
        "q0, q1 = qubits\n",
        "c0, c1 = clbits\n",
        "\n",
        "circuit.h([q0, q1])\n",
        "circuit.measure(q0, c0)\n",
        "circuit.measure(q1, c1)\n",
        "with circuit.while_loop((clbits, 0b11)):\n",
        "    circuit.h([q0, q1])\n",
        "    circuit.measure(q0, c0)\n",
        "    circuit.measure(q1, c1)\n",
        "\n",
        "circuit.draw(\"mpl\")\n",
        "\n",
        "# example output counts: {'01': 334, '10': 368, '00': 322}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "672080db-913d-4511-ab63-48ca48b60fa5",
      "metadata": {},
      "source": [
        "<span id=\"classical-expressions\" />\n",
        "\n",
        "## Espressioni classiche\n",
        "\n",
        "Il modulo [`qiskit.circuit.classical`](/docs/api/qiskit/circuit_classical) \"Espressione classica\" di Qiskit contiene una rappresentazione esplorativa delle operazioni eseguite in fase di esecuzione su valori classici durante l'esecuzione del circuito.\n",
        "\n",
        "L'esempio seguente mostra che è possibile utilizzare il calcolo della parità per creare uno stato GHZ a n-qubit utilizzando circuiti dinamici. In primo luogo, si generano $n/2$ coppie di Bell su qubit adiacenti. Quindi, incollare queste coppie utilizzando uno strato di porte CNOT tra le coppie. Si misura quindi il qubit target di tutte le porte CNOT precedenti e si resetta ogni qubit misurato allo stato $\\vert 0 \\rangle$. Si applica $X$ a ogni sito non misurato per il quale la parità di tutti i bit precedenti è dispari. Infine, le porte CNOT vengono applicate ai qubit misurati per ristabilire l'entanglement perso durante la misurazione.\n",
        "\n",
        "Nel calcolo della parità, il primo elemento dell'espressione costruita comporta il sollevamento dell'oggetto Python`mr[0]` a un [`Value`](/docs/api/qiskit/circuit_classical#value) nodo (`lift` viene utilizzato per trasformare oggetti arbitrari in espressioni classiche). Ciò non è necessario per `mr[1]` e il possibile registro classico seguente, poiché sono input per `expr.bit_xor`e qualsiasi sollevamento necessario viene eseguito automaticamente in questi casi. Tali espressioni possono essere costruite in loop e altri costrutti.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "8c8ad702-1097-411f-983d-b5654f75059f",
      "metadata": {},
      "outputs": [],
      "source": [
        "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit.circuit.classical import expr\n",
        "\n",
        "num_qubits = 8\n",
        "if num_qubits % 2 or num_qubits < 4:\n",
        "    raise ValueError(\"num_qubits must be an even integer ≥ 4\")\n",
        "meas_qubits = list(range(2, num_qubits, 2))  # qubits to measure and reset\n",
        "\n",
        "qr = QuantumRegister(num_qubits, \"qr\")\n",
        "mr = ClassicalRegister(len(meas_qubits), \"m\")\n",
        "qc = QuantumCircuit(qr, mr)\n",
        "\n",
        "# Create local Bell pairs\n",
        "qc.reset(qr)\n",
        "qc.h(qr[::2])\n",
        "for ctrl in range(0, num_qubits, 2):\n",
        "    qc.cx(qr[ctrl], qr[ctrl + 1])\n",
        "\n",
        "# Glue neighboring pairs\n",
        "for ctrl in range(1, num_qubits - 1, 2):\n",
        "    qc.cx(qr[ctrl], qr[ctrl + 1])\n",
        "\n",
        "# Measure boundary qubits between pairs,reset to 0\n",
        "for k, q in enumerate(meas_qubits):\n",
        "    qc.measure(qr[q], mr[k])\n",
        "    qc.reset(qr[q])\n",
        "\n",
        "# Parity-conditioned X corrections\n",
        "# Each non-measured qubit gets flipped iff the parity (XOR) of all\n",
        "# preceding measurement bits is 1\n",
        "for tgt in range(num_qubits):\n",
        "    if tgt in meas_qubits:  # skip measured qubits\n",
        "        continue\n",
        "    # all measurement registers whose physical qubit index < tgt\n",
        "    left_bits = [k for k, q in enumerate(meas_qubits) if q < tgt]\n",
        "    if not left_bits:  # skip if list empty\n",
        "        continue\n",
        "\n",
        "    # build XOR-parity expression\n",
        "    parity = expr.lift(\n",
        "        mr[left_bits[0]]\n",
        "    )  # lift the first bit to Value so it will be treated like a boolean.\n",
        "    for k in left_bits[1:]:\n",
        "        parity = expr.bit_xor(\n",
        "            mr[k], parity\n",
        "        )  # calculate parity with all other bits\n",
        "    with qc.if_test(parity):  # Add X if parity is 1\n",
        "        qc.x(qr[tgt])\n",
        "\n",
        "# Re-entangle measured qubits\n",
        "for ctrl in range(1, num_qubits - 1, 2):\n",
        "    qc.cx(qr[ctrl], qr[ctrl + 1])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "a5d808f5-d424-4133-a557-89d2f2a2c853",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/a5d808f5-d424-4133-a557-89d2f2a2c853-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "qc.draw(output=\"mpl\", style=\"iqp\", idle_wires=False, fold=-1)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "62134a85-608f-4ad2-a76e-b0736bec9362",
      "metadata": {},
      "source": [
        "<span id=\"store\" />\n",
        "\n",
        "<span id=\"store\" />\n",
        "\n",
        "### `Store`\n",
        "\n",
        "È possibile utilizzare l'istruzione [`store`](/docs/api/qiskit/circuit#store) per salvare il risultato di un'espressione classica, qualora tale espressione debba essere utilizzata più volte. Le operazioni vengono parallelizzate automaticamente, rendendo il codice notevolmente più efficiente in fase di esecuzione.\n",
        "\n",
        "Ad esempio, in fase di esecuzione è più naturale ed efficiente scrivere $B[0] \\oplus B[1] \\oplus B[2] \\ldots$, dove $B = \\neg A$, piuttosto che $(\\neg A[0]) \\oplus (\\neg A[1]) \\oplus (\\neg A[2]) \\ldots$. Nel primo caso, la negazione viene calcolata in un unico passaggio parallelo prima della catena XOR, invece di valutare sequenzialmente ogni negazione all'interno dell'espressione.\n",
        "\n",
        "Esempio completo:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "953fa3ca-f542-47ea-9cf2-36a616ecb7f7",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/guides/classical-feedforward-and-control-flow/extracted-outputs/953fa3ca-f542-47ea-9cf2-36a616ecb7f7-0.svg\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "from qiskit.circuit import QuantumCircuit, QuantumRegister, ClassicalRegister\n",
        "from qiskit.circuit.classical import expr\n",
        "\n",
        "qregs = QuantumRegister(4, \"q\")\n",
        "creg = ClassicalRegister(3, \"c\")\n",
        "# temp is a plain ClassicalRegister used as the store target\n",
        "temp = ClassicalRegister(3, \"temp\")\n",
        "qc = QuantumCircuit(qregs, creg, temp)\n",
        "\n",
        "qc.h([0, 1, 2])\n",
        "qc.measure([0, 1, 2], creg)\n",
        "\n",
        "# Store bit-NOT of the full 3-bit register into temp\n",
        "qc.store(temp, expr.bit_not(creg))\n",
        "\n",
        "# Compute parity of temp using bit-indexed XOR\n",
        "parity = expr.bit_xor(\n",
        "    expr.bit_xor(expr.index(temp, 0), expr.index(temp, 1)),\n",
        "    expr.index(temp, 2),\n",
        ")\n",
        "\n",
        "# Flip q3 if parity of ~creg is 1\n",
        "with qc.if_test(parity):\n",
        "    qc.x(3)\n",
        "\n",
        "qc.measure([0, 1, 2], creg)\n",
        "\n",
        "qc.draw(\"mpl\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "f1b55508-04e8-4f53-9b13-33302102711d",
      "metadata": {},
      "source": [
        "<span id=\"next-steps\" />\n",
        "\n",
        "## Passi successivi\n",
        "\n",
        "<Admonition type=\"tip\" title=\"Suggerimenti\">\n",
        "  * Scopri come implementare un disaccoppiamento dinamico accurato utilizzando [lo stretch](/docs/guides/stretch).\n",
        "  * Utilizza [la visualizzazione dello schema dei circuiti](/docs/guides/qiskit-runtime-circuit-timing) per eseguire il debug e ottimizzare i tuoi circuiti dinamici.\n",
        "  * [Eseguire circuiti dinamici](/docs/guides/execute-dynamic-circuits).\n",
        "</Admonition>\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "id": "a1b8767d",
      "source": "© IBM Corp., 2017-2026"
    }
  ],
  "metadata": {
    "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"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}