{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "b6d1e3ec",
      "metadata": {},
      "source": [
        "---\n",
        "title: \"Otimização binária de ordem superior com o Optimization Solver da Q-CTRL\"\n",
        "description: \"Resolva um problema de otimização quântica em escala utilitária usando o Solucionador de Otimização, uma função Qiskit da Q-CTRL Fire Opal\"\n",
        "---\n",
        "\n",
        "{/* cspell:ignore nrows ncols lambdify ILOG histtype stepfilled */}\n",
        "\n",
        "<span id=\"higher-order-binary-optimization-with-q-ctrls-optimization-solver\" />\n",
        "\n",
        "# Otimização binária de ordem superior com o Optimization Solver da Q-CTRL\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "a6f69b77",
      "metadata": {},
      "source": [
        "<Admonition type=\"note\" title=\"Nota\">\n",
        "  As funções do Qiskit são um recurso experimental disponível apenas para usuários dos planos IBM Quantum® Premium Plan, Flex Plan e On-Prem (via IBM Quantum Platform API). Eles estão no status de versão prévia e estão sujeitos a alterações.\n",
        "</Admonition>\n",
        "\n",
        "*Estimativa de uso: 24 minutos em um processador Heron r2. (OBSERVAÇÃO: essa é apenas uma estimativa. Seu tempo de execução pode variar)*\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8bf80006",
      "metadata": {},
      "source": [
        "<span id=\"background\" />\n",
        "\n",
        "## Segundo plano\n",
        "\n",
        "Este tutorial demonstra como resolver um problema de otimização binária de ordem superior (HOBO) usando o [Optimization Solver, uma função Qiskit do Q-CTRL Fire Opal](/docs/guides/q-ctrl-optimization-solver). O exemplo demonstrado neste tutorial é um problema de otimização projetado para encontrar a energia do estado fundamental de um modelo Ising de 156 qubits de ligação aleatória que possui termos cúbicos. O Optimization Solver pode ser usado para problemas gerais de otimização que podem ser definidos como uma função objetiva.\n",
        "\n",
        "A otimização automatiza totalmente as etapas de implementação com reconhecimento de hardware da solução de problemas de otimização em hardware quântico e, ao aproveitar o [Gerenciamento de Desempenho](/docs/guides/q-ctrl-performance-management) para a execução quântica, obtém soluções precisas em escala de utilidade. Para obter um resumo detalhado do fluxo de trabalho completo do Optimization Solver e dos resultados de benchmarking, consulte [o manuscrito publicado](https://arxiv.org/abs/2406.01743).\n",
        "\n",
        "Este tutorial apresenta as etapas a seguir:\n",
        "\n",
        "1. Defina o problema como uma função objetiva\n",
        "2. Execute o algoritmo híbrido usando o solucionador de otimização Fire Opal\n",
        "3. avaliar resultados\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "55b94021",
      "metadata": {},
      "source": [
        "<span id=\"requirements\" />\n",
        "\n",
        "## Requisitos\n",
        "\n",
        "Antes de iniciar este tutorial, verifique se você tem os seguintes itens instalados:\n",
        "\n",
        "* Funções do Qiskit (`pip install qiskit-ibm-catalog`)\n",
        "* SymPy (`pip install sympy`)\n",
        "\n",
        "Você também precisará obter acesso à função Optimization Solver. [Preencha o formulário](/functions?id=q-ctrl-optimization-solver) para solicitar acesso.\n",
        "\n"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "7db2e559",
      "metadata": {},
      "source": [
        "<span id=\"setup\" />\n",
        "\n",
        "## Instalação\n",
        "\n",
        "Primeiro, importe os pacotes e as ferramentas necessárias.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "c262cb27",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Qiskit Functions Catalog\n",
        "from qiskit_ibm_catalog import QiskitFunctionsCatalog\n",
        "\n",
        "# SymPy tools for constructing objective function\n",
        "from sympy import Poly\n",
        "from sympy import symbols, srepr\n",
        "\n",
        "# Tools for plotting and evaluating results\n",
        "import numpy as np\n",
        "import matplotlib.pyplot as plt\n",
        "from sympy import lambdify"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "df157bba",
      "metadata": {},
      "source": [
        "Defina suas credenciais da [IBM Quantum Platform](/), que serão usadas em todo o tutorial para autenticar o Qiskit Runtime e o Qiskit Functions.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "b92bd67d",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Credentials\n",
        "\n",
        "# For `token`, use the 44-character API_KEY you created\n",
        "# and saved from the IBM Quantum Platform Home dashboard\n",
        "token = \"<YOUR-API_KEY>\"\n",
        "instance = \"<YOUR_CRN>\""
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "988ee237",
      "metadata": {},
      "source": [
        "<span id=\"step-1-define-the-problem-as-an-objective-function\" />\n",
        "\n",
        "## Passo 1: Defina o problema como uma função objetiva\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "6c9bffae",
      "metadata": {},
      "source": [
        "O Solver de otimização aceita uma função objetiva ou um gráfico como entrada. Neste tutorial, o problema de minimização do vidro de spin Ising é definido como uma função objetiva e foi adaptado para a topologia heavy-hex dos dispositivos IBM®.\n",
        "\n",
        "Como essa função objetiva contém termos cúbicos, quadráticos e lineares, ela se enquadra na classe de problemas HOBO, conhecida por ser consideravelmente mais complicada de resolver do que os problemas convencionais de otimização binária quadrática sem restrições (QUBO).\n",
        "\n",
        "Para uma discussão detalhada da construção da definição do problema e dos resultados anteriores obtidos com o Optimization Solver, consulte [este manuscrito técnico](https://arxiv.org/abs/2406.01743). O problema foi originalmente definido e avaliado como parte de um [artigo publicado pelo Los Alamos National Laboratory](https://arxiv.org/abs/2312.00997) e foi adaptado para aproveitar a largura total do dispositivo dos processadores Quantum Heron de 156 qubit IBM.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 42,
      "id": "0ad66539",
      "metadata": {},
      "outputs": [],
      "source": [
        "qubit_count = 156\n",
        "\n",
        "# Create symbolic variables to represent qubits\n",
        "x = symbols([f\"x[{i}]\" for i in range(qubit_count)])\n",
        "\n",
        "# # Define a polynomial representing a spin glass model\n",
        "spin_glass_poly = Poly(\n",
        "    -4 * x[0] * x[1]\n",
        "    - 8 * x[1] * x[2] * x[3]\n",
        "    + 8 * x[1] * x[2]\n",
        "    + 4 * x[1] * x[3]\n",
        "    - 4 * x[2]\n",
        "    + 8 * x[3] * x[4] * x[5]\n",
        "    - 4 * x[3] * x[5]\n",
        "    - 8 * x[3] * x[16] * x[23]\n",
        "    + 4 * x[3] * x[23]\n",
        "    - 2 * x[3]\n",
        "    - 4 * x[4]\n",
        "    - 8 * x[5] * x[6] * x[7]\n",
        "    + 8 * x[5] * x[6]\n",
        "    + 4 * x[5] * x[7]\n",
        "    - 2 * x[5]\n",
        "    + 8 * x[6] * x[7]\n",
        "    - 4 * x[6]\n",
        "    - 8 * x[7] * x[8] * x[9]\n",
        "    + 4 * x[7] * x[9]\n",
        "    - 8 * x[7] * x[17] * x[27]\n",
        "    + 4 * x[7] * x[27]\n",
        "    - 6 * x[7]\n",
        "    + 8 * x[8] * x[9]\n",
        "    + 8 * x[9] * x[10] * x[11]\n",
        "    - 4 * x[9] * x[11]\n",
        "    - 2 * x[9]\n",
        "    - 8 * x[10] * x[11]\n",
        "    + 4 * x[10]\n",
        "    - 8 * x[11] * x[12] * x[13]\n",
        "    + 4 * x[11] * x[13]\n",
        "    - 8 * x[11] * x[18] * x[31]\n",
        "    + 8 * x[11] * x[18]\n",
        "    + 4 * x[11] * x[31]\n",
        "    - 2 * x[11]\n",
        "    + 8 * x[12] * x[13]\n",
        "    + 8 * x[13] * x[14] * x[15]\n",
        "    - 4 * x[13] * x[15]\n",
        "    - 2 * x[13]\n",
        "    - 8 * x[14] * x[15]\n",
        "    + 4 * x[14]\n",
        "    - 8 * x[15] * x[19] * x[35]\n",
        "    + 8 * x[15] * x[19]\n",
        "    + 4 * x[15] * x[35]\n",
        "    - 2 * x[15]\n",
        "    + 8 * x[16] * x[23]\n",
        "    + 8 * x[17] * x[27]\n",
        "    - 4 * x[17]\n",
        "    + 8 * x[18] * x[31]\n",
        "    - 8 * x[18]\n",
        "    + 8 * x[19] * x[35]\n",
        "    - 8 * x[19]\n",
        "    + 4 * x[20] * x[21]\n",
        "    - 4 * x[20]\n",
        "    - 8 * x[21] * x[22] * x[23]\n",
        "    + 8 * x[21] * x[22]\n",
        "    + 4 * x[21] * x[23]\n",
        "    - 8 * x[21] * x[36] * x[41]\n",
        "    + 4 * x[21] * x[41]\n",
        "    - 4 * x[21]\n",
        "    + 8 * x[22] * x[23]\n",
        "    - 8 * x[22]\n",
        "    + 8 * x[23] * x[24] * x[25]\n",
        "    - 4 * x[23] * x[25]\n",
        "    - 10 * x[23]\n",
        "    - 8 * x[24] * x[25]\n",
        "    + 8 * x[25] * x[26] * x[27]\n",
        "    - 8 * x[25] * x[26]\n",
        "    - 4 * x[25] * x[27]\n",
        "    + 8 * x[25] * x[37] * x[45]\n",
        "    - 8 * x[25] * x[37]\n",
        "    - 4 * x[25] * x[45]\n",
        "    + 14 * x[25]\n",
        "    - 8 * x[26] * x[27]\n",
        "    + 4 * x[26]\n",
        "    + 8 * x[27] * x[28] * x[29]\n",
        "    - 4 * x[27] * x[29]\n",
        "    - 2 * x[27]\n",
        "    - 8 * x[28] * x[29]\n",
        "    - 8 * x[29] * x[30] * x[31]\n",
        "    + 4 * x[29] * x[31]\n",
        "    + 8 * x[29] * x[38] * x[49]\n",
        "    - 8 * x[29] * x[38]\n",
        "    - 4 * x[29] * x[49]\n",
        "    + 6 * x[29]\n",
        "    + 8 * x[30] * x[31]\n",
        "    - 4 * x[30]\n",
        "    - 8 * x[31] * x[32] * x[33]\n",
        "    + 4 * x[31] * x[33]\n",
        "    - 6 * x[31]\n",
        "    + 8 * x[33] * x[34] * x[35]\n",
        "    - 4 * x[33] * x[35]\n",
        "    - 8 * x[33] * x[39] * x[53]\n",
        "    + 8 * x[33] * x[39]\n",
        "    + 4 * x[33] * x[53]\n",
        "    - 6 * x[33]\n",
        "    - 8 * x[34] * x[35]\n",
        "    + 2 * x[35]\n",
        "    + 8 * x[36] * x[41]\n",
        "    - 8 * x[37] * x[45]\n",
        "    + 4 * x[37]\n",
        "    - 8 * x[38] * x[49]\n",
        "    + 4 * x[38]\n",
        "    + 4 * x[40] * x[41]\n",
        "    - 8 * x[41] * x[42] * x[43]\n",
        "    + 4 * x[41] * x[43]\n",
        "    - 8 * x[41]\n",
        "    + 8 * x[42] * x[43]\n",
        "    - 4 * x[42]\n",
        "    - 8 * x[43] * x[44] * x[45]\n",
        "    + 8 * x[43] * x[44]\n",
        "    + 4 * x[43] * x[45]\n",
        "    - 8 * x[43] * x[56] * x[63]\n",
        "    + 4 * x[43] * x[63]\n",
        "    - 6 * x[43]\n",
        "    - 4 * x[44]\n",
        "    - 8 * x[45] * x[46] * x[47]\n",
        "    + 4 * x[45] * x[47]\n",
        "    + 2 * x[45]\n",
        "    + 4 * x[46]\n",
        "    - 8 * x[47] * x[48] * x[49]\n",
        "    + 8 * x[47] * x[48]\n",
        "    + 4 * x[47] * x[49]\n",
        "    - 8 * x[47] * x[57] * x[67]\n",
        "    + 4 * x[47] * x[67]\n",
        "    - 2 * x[47]\n",
        "    - 4 * x[48]\n",
        "    - 8 * x[49] * x[50] * x[51]\n",
        "    + 8 * x[49] * x[50]\n",
        "    + 4 * x[49] * x[51]\n",
        "    - 2 * x[49]\n",
        "    + 8 * x[50] * x[51]\n",
        "    - 8 * x[50]\n",
        "    - 8 * x[51] * x[52] * x[53]\n",
        "    + 8 * x[51] * x[52]\n",
        "    + 4 * x[51] * x[53]\n",
        "    - 8 * x[51] * x[58] * x[71]\n",
        "    + 4 * x[51] * x[71]\n",
        "    - 6 * x[51]\n",
        "    + 8 * x[52] * x[53]\n",
        "    - 8 * x[52]\n",
        "    + 8 * x[53] * x[54] * x[55]\n",
        "    - 8 * x[53] * x[54]\n",
        "    - 4 * x[53] * x[55]\n",
        "    - 2 * x[53]\n",
        "    + 4 * x[54]\n",
        "    - 8 * x[55] * x[59] * x[75]\n",
        "    + 4 * x[55] * x[75]\n",
        "    - 2 * x[55]\n",
        "    + 8 * x[56] * x[63]\n",
        "    + 8 * x[57] * x[67]\n",
        "    - 4 * x[57]\n",
        "    + 8 * x[58] * x[71]\n",
        "    + 8 * x[59] * x[75]\n",
        "    - 4 * x[59]\n",
        "    + 4 * x[60] * x[61]\n",
        "    + 8 * x[61] * x[62] * x[63]\n",
        "    - 4 * x[61] * x[63]\n",
        "    + 8 * x[61] * x[76] * x[81]\n",
        "    - 8 * x[61] * x[76]\n",
        "    - 4 * x[61] * x[81]\n",
        "    - 8 * x[63] * x[64] * x[65]\n",
        "    + 8 * x[63] * x[64]\n",
        "    + 4 * x[63] * x[65]\n",
        "    - 6 * x[63]\n",
        "    + 8 * x[65] * x[66] * x[67]\n",
        "    - 8 * x[65] * x[66]\n",
        "    - 4 * x[65] * x[67]\n",
        "    - 8 * x[65] * x[77] * x[85]\n",
        "    + 4 * x[65] * x[85]\n",
        "    + 2 * x[65]\n",
        "    + 4 * x[66]\n",
        "    - 8 * x[67] * x[68] * x[69]\n",
        "    + 8 * x[67] * x[68]\n",
        "    + 4 * x[67] * x[69]\n",
        "    - 10 * x[67]\n",
        "    + 8 * x[68] * x[69]\n",
        "    - 4 * x[68]\n",
        "    + 8 * x[69] * x[70] * x[71]\n",
        "    - 4 * x[69] * x[71]\n",
        "    - 8 * x[69] * x[78] * x[89]\n",
        "    + 4 * x[69] * x[89]\n",
        "    - 6 * x[69]\n",
        "    + 8 * x[71] * x[72] * x[73]\n",
        "    - 8 * x[71] * x[72]\n",
        "    - 4 * x[71] * x[73]\n",
        "    + 2 * x[71]\n",
        "    - 8 * x[72] * x[73]\n",
        "    + 8 * x[72]\n",
        "    - 8 * x[73] * x[74] * x[75]\n",
        "    + 8 * x[73] * x[74]\n",
        "    + 4 * x[73] * x[75]\n",
        "    - 8 * x[73] * x[79] * x[93]\n",
        "    + 8 * x[73] * x[79]\n",
        "    + 4 * x[73] * x[93]\n",
        "    - 6 * x[73]\n",
        "    + 8 * x[74] * x[75]\n",
        "    - 4 * x[74]\n",
        "    - 10 * x[75]\n",
        "    + 4 * x[76]\n",
        "    + 8 * x[78] * x[89]\n",
        "    - 4 * x[78]\n",
        "    - 4 * x[79]\n",
        "    - 4 * x[80] * x[81]\n",
        "    + 4 * x[80]\n",
        "    - 8 * x[81] * x[82] * x[83]\n",
        "    + 8 * x[81] * x[82]\n",
        "    + 4 * x[81] * x[83]\n",
        "    + 8 * x[82] * x[83]\n",
        "    - 8 * x[82]\n",
        "    - 8 * x[83] * x[84] * x[85]\n",
        "    + 4 * x[83] * x[85]\n",
        "    - 8 * x[83] * x[96] * x[103]\n",
        "    + 4 * x[83] * x[103]\n",
        "    - 2 * x[83]\n",
        "    - 8 * x[85] * x[86] * x[87]\n",
        "    + 8 * x[85] * x[86]\n",
        "    + 4 * x[85] * x[87]\n",
        "    - 6 * x[85]\n",
        "    + 8 * x[86] * x[87]\n",
        "    - 4 * x[86]\n",
        "    - 8 * x[87] * x[88] * x[89]\n",
        "    + 4 * x[87] * x[89]\n",
        "    + 8 * x[87] * x[97] * x[107]\n",
        "    - 8 * x[87] * x[97]\n",
        "    - 4 * x[87] * x[107]\n",
        "    + 2 * x[87]\n",
        "    + 4 * x[88]\n",
        "    - 8 * x[89] * x[90] * x[91]\n",
        "    + 8 * x[89] * x[90]\n",
        "    + 4 * x[89] * x[91]\n",
        "    - 10 * x[89]\n",
        "    + 8 * x[90] * x[91]\n",
        "    - 8 * x[90]\n",
        "    - 8 * x[91] * x[92] * x[93]\n",
        "    + 4 * x[91] * x[93]\n",
        "    - 8 * x[91] * x[98] * x[111]\n",
        "    + 8 * x[91] * x[98]\n",
        "    + 4 * x[91] * x[111]\n",
        "    - 10 * x[91]\n",
        "    + 8 * x[92] * x[93]\n",
        "    - 4 * x[92]\n",
        "    - 8 * x[93] * x[94] * x[95]\n",
        "    + 4 * x[93] * x[95]\n",
        "    - 6 * x[93]\n",
        "    + 8 * x[95] * x[99] * x[115]\n",
        "    - 8 * x[95] * x[99]\n",
        "    - 4 * x[95] * x[115]\n",
        "    + 2 * x[95]\n",
        "    + 4 * x[96]\n",
        "    - 8 * x[97] * x[107]\n",
        "    + 4 * x[97]\n",
        "    - 4 * x[98]\n",
        "    - 8 * x[99] * x[115]\n",
        "    + 4 * x[99]\n",
        "    - 4 * x[100] * x[101]\n",
        "    + 8 * x[101] * x[102] * x[103]\n",
        "    - 8 * x[101] * x[102]\n",
        "    - 4 * x[101] * x[103]\n",
        "    - 8 * x[101] * x[116] * x[121]\n",
        "    + 8 * x[101] * x[116]\n",
        "    + 4 * x[101] * x[121]\n",
        "    + 4 * x[101]\n",
        "    - 8 * x[103] * x[104] * x[105]\n",
        "    + 4 * x[103] * x[105]\n",
        "    + 2 * x[103]\n",
        "    + 8 * x[105] * x[106] * x[107]\n",
        "    - 4 * x[105] * x[107]\n",
        "    - 8 * x[105] * x[117] * x[125]\n",
        "    + 4 * x[105] * x[125]\n",
        "    + 2 * x[105]\n",
        "    - 8 * x[106] * x[107]\n",
        "    + 4 * x[106]\n",
        "    + 8 * x[107] * x[108] * x[109]\n",
        "    - 4 * x[107] * x[109]\n",
        "    + 6 * x[107]\n",
        "    - 4 * x[108]\n",
        "    + 8 * x[109] * x[110] * x[111]\n",
        "    - 4 * x[109] * x[111]\n",
        "    - 8 * x[109] * x[118] * x[129]\n",
        "    + 4 * x[109] * x[129]\n",
        "    + 2 * x[109]\n",
        "    - 8 * x[110] * x[111]\n",
        "    + 4 * x[110]\n",
        "    - 8 * x[111] * x[112] * x[113]\n",
        "    + 8 * x[111] * x[112]\n",
        "    + 4 * x[111] * x[113]\n",
        "    + 2 * x[111]\n",
        "    + 8 * x[112] * x[113]\n",
        "    - 8 * x[112]\n",
        "    - 8 * x[113] * x[114] * x[115]\n",
        "    + 4 * x[113] * x[115]\n",
        "    - 8 * x[113] * x[119] * x[133]\n",
        "    + 4 * x[113] * x[133]\n",
        "    - 2 * x[113]\n",
        "    + 6 * x[115]\n",
        "    - 4 * x[116]\n",
        "    + 4 * x[118]\n",
        "    + 4 * x[119]\n",
        "    + 4 * x[120] * x[121]\n",
        "    - 8 * x[121] * x[122] * x[123]\n",
        "    + 4 * x[121] * x[123]\n",
        "    - 4 * x[121]\n",
        "    + 4 * x[122]\n",
        "    - 8 * x[123] * x[124] * x[125]\n",
        "    + 4 * x[123] * x[125]\n",
        "    - 8 * x[123] * x[136] * x[143]\n",
        "    + 4 * x[123] * x[143]\n",
        "    - 2 * x[123]\n",
        "    + 8 * x[124] * x[125]\n",
        "    - 4 * x[124]\n",
        "    + 8 * x[125] * x[126] * x[127]\n",
        "    - 8 * x[125] * x[126]\n",
        "    - 4 * x[125] * x[127]\n",
        "    + 2 * x[125]\n",
        "    - 8 * x[127] * x[128] * x[129]\n",
        "    + 8 * x[127] * x[128]\n",
        "    + 4 * x[127] * x[129]\n",
        "    + 8 * x[127] * x[137] * x[147]\n",
        "    - 8 * x[127] * x[137]\n",
        "    - 4 * x[127] * x[147]\n",
        "    - 2 * x[127]\n",
        "    + 8 * x[129] * x[130] * x[131]\n",
        "    - 4 * x[129] * x[131]\n",
        "    + 2 * x[129]\n",
        "    - 4 * x[130]\n",
        "    - 8 * x[131] * x[132] * x[133]\n",
        "    + 4 * x[131] * x[133]\n",
        "    - 8 * x[131] * x[138] * x[151]\n",
        "    + 4 * x[131] * x[151]\n",
        "    - 2 * x[131]\n",
        "    + 8 * x[133] * x[134] * x[135]\n",
        "    - 4 * x[133] * x[135]\n",
        "    + 2 * x[133]\n",
        "    - 8 * x[134] * x[135]\n",
        "    + 4 * x[134]\n",
        "    - 8 * x[135] * x[139] * x[155]\n",
        "    + 8 * x[135] * x[139]\n",
        "    + 4 * x[135] * x[155]\n",
        "    + 2 * x[135]\n",
        "    + 8 * x[136] * x[143]\n",
        "    - 4 * x[136]\n",
        "    + 4 * x[138]\n",
        "    + 8 * x[139] * x[155]\n",
        "    - 4 * x[139]\n",
        "    - 4 * x[140] * x[141]\n",
        "    - 8 * x[141] * x[142] * x[143]\n",
        "    + 8 * x[141] * x[142]\n",
        "    + 4 * x[141] * x[143]\n",
        "    + 8 * x[142] * x[143]\n",
        "    - 8 * x[142]\n",
        "    - 8 * x[143] * x[144] * x[145]\n",
        "    + 8 * x[143] * x[144]\n",
        "    + 4 * x[143] * x[145]\n",
        "    - 14 * x[143]\n",
        "    + 8 * x[144] * x[145]\n",
        "    - 8 * x[144]\n",
        "    - 8 * x[145] * x[146] * x[147]\n",
        "    + 8 * x[145] * x[146]\n",
        "    + 4 * x[145] * x[147]\n",
        "    - 6 * x[145]\n",
        "    + 8 * x[146] * x[147]\n",
        "    - 4 * x[146]\n",
        "    - 8 * x[147] * x[148] * x[149]\n",
        "    + 8 * x[147] * x[148]\n",
        "    + 4 * x[147] * x[149]\n",
        "    - 6 * x[147]\n",
        "    - 4 * x[148]\n",
        "    - 8 * x[149] * x[150] * x[151]\n",
        "    + 8 * x[149] * x[150]\n",
        "    + 4 * x[149] * x[151]\n",
        "    - 6 * x[149]\n",
        "    + 8 * x[151] * x[152] * x[153]\n",
        "    - 4 * x[151] * x[153]\n",
        "    + 2 * x[151]\n",
        "    + 8 * x[153] * x[154] * x[155]\n",
        "    - 8 * x[153] * x[154]\n",
        "    - 4 * x[153] * x[155]\n",
        "    + 2 * x[153]\n",
        "    - 8 * x[154] * x[155]\n",
        "    + 4 * x[154]\n",
        "    - 2 * x[155]\n",
        "    + 46,\n",
        "    x,\n",
        "    domain=\"ZZ\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ac6f36e3",
      "metadata": {},
      "source": [
        "<span id=\"step-2-run-the-hybrid-algorithm-using-the-fire-opal-optimization-solver\" />\n",
        "\n",
        "## Etapa 2: Execute o algoritmo híbrido usando o Solucionador de Otimização Fire Opal\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "13ba6d0c",
      "metadata": {},
      "source": [
        "Agora, use a função Optimization Solver Qiskit para executar o algoritmo. Nos bastidores, o Optimization Solver se encarrega de mapear o problema para um algoritmo quântico híbrido, executar os circuitos quânticos com supressão de erros e realizar a otimização clássica.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bd38bb1e",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Authenticate to the Qiskit Functions Catalog\n",
        "catalog = QiskitFunctionsCatalog(\n",
        "    token=token,\n",
        "    instance=instance,\n",
        ")\n",
        "\n",
        "# Load the function\n",
        "solver = catalog.load(\"q-ctrl/optimization_solver\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "12cfe6f5",
      "metadata": {},
      "source": [
        "Verifique se o dispositivo escolhido tem pelo menos 156 qubits.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a27adab7",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Specify the target backend name\n",
        "backend_name = \"<CHOOSE_A_BACKEND>\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ffbe9f79",
      "metadata": {},
      "source": [
        "O Solver aceita uma representação de string da função objetiva.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 43,
      "id": "1834cb22",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Convert the objective function to string format\n",
        "spin_glass_poly_as_str = srepr(spin_glass_poly)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "98213fe9",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Run the problem\n",
        "spin_glass_job = solver.run(\n",
        "    problem=spin_glass_poly_as_str,\n",
        "    run_options={\"backend_name\": backend_name},\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "d25caa83",
      "metadata": {},
      "source": [
        "Você pode usar as conhecidas [APIs Qiskit Serverless](/docs/guides/serverless) para verificar o status da sua carga de trabalho da função Qiskit:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "77a8ded0",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Get job status\n",
        "spin_glass_job.status()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "7cd96271",
      "metadata": {},
      "source": [
        "O Solver retorna um dicionário com a solução e os metadados associados, como a bitstring da solução, o número de iterações e o mapeamento de variáveis para a bitstring. Para obter uma definição completa das entradas e saídas do Solver, consulte a [documentação]().\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "bd8bd878",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Poll for results\n",
        "result = spin_glass_job.result()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 54,
      "id": "2bddbcbc",
      "metadata": {},
      "outputs": [],
      "source": [
        "# Get the final bitstring distribution and set the number of shots\n",
        "distribution = result[\"final_bitstring_distribution\"]"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "50b94af2",
      "metadata": {},
      "source": [
        "<span id=\"step-3-evaluate-results\" />\n",
        "\n",
        "## Etapa 3: Avaliar os resultados\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "id": "f6f6e93a",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Minimum ground state energy: -242.0\n"
          ]
        }
      ],
      "source": [
        "# Get the solution ground state energy\n",
        "print(f\"Minimum ground state energy: {result[\"solution_bitstring_cost\"]}\")"
      ]
    },
    {
      "attachments": {},
      "cell_type": "markdown",
      "id": "733431ad",
      "metadata": {},
      "source": [
        "O Solver encontrou a solução correta, que foi validada usando o software de otimização clássico. A complexidade desse problema de escala de serviços públicos exige um software de otimização avançado para ser resolvido de forma clássica, como o [IBM ILOG CPLEX Optimization Studio (CPLEX)](https://www.ibm.com/products/ilog-cplex-optimization-studio) ou o [Gurobi Optimization](https://www.gurobi.com/).\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "40406a33",
      "metadata": {},
      "source": [
        "Como uma análise visual da qualidade dos resultados, você pode plotar os resultados calculando os valores de custo das cadeias de bits e suas probabilidades. Para fins de comparação, trace os resultados ao lado de uma distribuição de cadeias de bits amostradas aleatoriamente, o que equivale a uma solução clássica de \"força bruta\". Se o algoritmo encontrar consistentemente custos mais baixos, isso sugere que o algoritmo quântico está resolvendo efetivamente o problema de otimização.\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "a481c257",
      "metadata": {},
      "outputs": [],
      "source": [
        "def plot_cost_histogram(\n",
        "    costs, probabilities, distribution, qubit_count, bitstring_cost\n",
        "):\n",
        "    \"\"\"Plots a histogram comparing the cost distributions of\n",
        "    Q-CTRL Solver and random sampling.\"\"\"\n",
        "\n",
        "    # Set figure DPI for higher resolution and font size for labels\n",
        "    plt.rcParams[\"figure.dpi\"] = 300\n",
        "    plt.rcParams.update({\"font.size\": 6})  # Set default font size to 6\n",
        "\n",
        "    # Define labels and colors for the plot\n",
        "    labels = [\"Q-CTRL Solver\", \"Random Sampling\"]\n",
        "    colors = [\"#680CE9\", \"#E04542\"]\n",
        "\n",
        "    # Calculate total shots (total number of bitstrings in the distribution)\n",
        "    shots = sum(distribution.values())\n",
        "\n",
        "    # Generate random bitstrings for comparison (random sampling)\n",
        "    rng = np.random.default_rng(seed=0)\n",
        "    random_array = rng.integers(\n",
        "        0, 2, size=(shots, qubit_count)\n",
        "    )  # Generate random bitstrings (0 or 1 for each qubit)\n",
        "    random_bitstrings = [\"\".join(row.astype(str)) for row in random_array]\n",
        "\n",
        "    # Compute the cost for each random bitstring\n",
        "    random_costs = [bitstring_cost(k) for k in random_bitstrings]\n",
        "\n",
        "    # Set uniform probabilities for the random sampling\n",
        "    random_probabilities = (\n",
        "        np.ones(shape=(shots,)) / shots\n",
        "    )  # Equal probability for each random bitstring\n",
        "\n",
        "    # Find the minimum and maximum costs for binning the histogram\n",
        "    min_cost = np.min(costs)\n",
        "    max_cost = np.max(random_costs)\n",
        "\n",
        "    # Create a histogram plot with a smaller figure size (4x2 inches)\n",
        "    fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(4, 2))\n",
        "\n",
        "    # Plot histograms for the Q-CTRL solver and random sampling costs\n",
        "    _, _, _ = ax.hist(\n",
        "        [costs, random_costs],  # Data for the two histograms\n",
        "        np.arange(min_cost, max_cost, 2),  # Bins for the histogram\n",
        "        weights=[\n",
        "            probabilities,\n",
        "            random_probabilities,\n",
        "        ],  # Probabilities for each data set\n",
        "        label=labels,  # Labels for the legend\n",
        "        color=colors,  # Colors for each histogram\n",
        "        histtype=\"stepfilled\",  # Filled step histogram\n",
        "        align=\"mid\",  # Align bars to the bin center\n",
        "        alpha=0.8,  # Transparency\n",
        "    )\n",
        "\n",
        "    # Set the x and y labels for the plot\n",
        "    ax.set_xlabel(\"Cost\")\n",
        "    ax.set_ylabel(\"Probability\")\n",
        "\n",
        "    # Add the legend to the plot\n",
        "    ax.legend()\n",
        "\n",
        "    # Show the plot\n",
        "    plt.show()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 59,
      "id": "a2fe3966",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Image src=\"/docs/images/tutorials/solve-higher-order-binary-optimization-problems-with-q-ctrls-optimization-solver/extracted-outputs/a2fe3966-0.avif\" alt=\"Output of the previous code cell\" />"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Convert spin_glass_poly into a NumPy-compatible function\n",
        "poly_as_numpy_function = lambdify(x, spin_glass_poly.as_expr(), \"numpy\")\n",
        "\n",
        "\n",
        "# Function to compute the cost of a given bitstring using spin_glass_poly\n",
        "def bitstring_cost(bitstring: str) -> float:\n",
        "    # Convert bitstring to a reversed list of integers (0s and 1s)\n",
        "    return float(\n",
        "        poly_as_numpy_function(*[int(b) for b in str(bitstring[::-1])])\n",
        "    )\n",
        "\n",
        "\n",
        "# Calculate the cost of each bitstring in the distribution\n",
        "costs = [bitstring_cost(k) for k, _ in distribution.items()]\n",
        "\n",
        "# Extract probabilities from the bitstring distribution\n",
        "probabilities = np.array([v for _, v in distribution.items()])\n",
        "probabilities = probabilities / sum(\n",
        "    probabilities\n",
        ")  # Normalize to get probabilities\n",
        "\n",
        "plot_cost_histogram(\n",
        "    costs, probabilities, distribution, qubit_count, bitstring_cost\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "15e35cff",
      "metadata": {},
      "source": [
        "Como o objetivo desse algoritmo de otimização é encontrar o estado fundamental mínimo do modelo de Ising, valores mais baixos indicam soluções melhores. Portanto, é visualmente evidente que as soluções geradas pelo Fire Opal Optimization Solver superam em muito a seleção aleatória.\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"
    },
    "hours": 1,
    "qpuSeconds": 1440
  },
  "nbformat": 4,
  "nbformat_minor": 5
}