{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Converters for OptimizationProblem\n", "## Overview\n", "This module provides various converters to transform optimization problems into different forms.\n", "These converters can be used to change variable types, objective functions, and constraints.\n", "In general, quantum algorithms require a specific formulation of an optimization problem, so we often need to convert our problem into the right type.\n", "\n", "For example, the QUBO (Quadratic Unconstrained Binary Optimization) format is widely used in quantum computing.\n", "The `OptimizationProblemToQubo` converter transforms an `OptimizationProblem` into QUBO form by converting variables to binary and eliminating constraints.\n", "Some quantum algorithms can also handle higher-order terms. In such cases, the `OptimizationProblemToHubo` converter transforms an `OptimizationProblem` into a HUBO (Higher-order Unconstrained Binary Optimization) format.\n", "\n", "Both QUBO and HUBO problems can be mapped to Ising Hamiltonians by the `to_ising()` function. Both binary variables and spin variables are supported.\n", "In Optimization add-on, these are represented by the `qiskit.quantum_info.SparsePauliOp` object.\n", "\n", "The converters provided in this module include:\n", "- `BinaryToSpin`: Converts binary variables to spin variables.\n", "- `SpinToBinary`: Converts spin variables to binary variables.\n", "- `IntegerToBinary`: Converts integer variables to binary variables.\n", "- `InequalityToEquality`: Converts inequality constraints to equality constraints using slack variables.\n", "- `EqualityToPenalty`: Converts equality constraints to penalty terms in the objective function.\n", "- `LinearInequalityToPenalty`: Converts specific linear inequality constraints to penalty terms in the objective function with fewer additional variables.\n", "- `MaximizeToMinimize`: Converts a maximization objective to a minimization objective.\n", "- `MinimizeToMaximize`: Converts a minimization objective to a maximization objective.\n", "- `OptimizationProblemToQubo`: Converts `OptimizationProblem` in to a QUBO format. It's a combination of several converters: `IntegerToBinary`, , `InequalityToPenalty`, `InequalityToEquality`, `EqualityToPenalty`, and `MaximizeToMinimize`. This converter will raise an exception if high-order terms are present.\n", "- `OptimizationProblemToHubo`: Converts an `OptimizationProblem` to a HUBO format. It's also a combination of several converters: `IntegerToBinary`, `InequalityToPenalty`, `EqualityToPenalty`, and `MaximizeToMinimize`, while preserving higher-order terms in the objective function.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Code Examples\n", "\n", "### Integer to Binary Conversion\n", "`IntegerToBinary` onverts integer variables into binary variables and adjusts the corresponding coefficients to eliminate integer variables from an `OptimizationProblem`. For this conversion, the bounded-coefficient encoding proposed in [arxiv:1706.01945](https://arxiv.org/abs/1706.01945) (Eq. (5)) is used. In this encoding, an integer variable $x$ with bounds $l \\leq x \\leq u$ is represented using binary variables $b_i$ as follows:\n", "\n", "$x = l + \\sum_{i=0}^{k-1} 2^i b_i + (u - l + 1 - 2^k) b_k$\n", "where $k = \\lceil \\log_2(u - l + 1) \\rceil$. This encoding minimizes the number of binary variables required to represent the integer variable while ensuring that the bounds are respected.\n", "\n", "For more details on the encoding method, please refer to the paper." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Problem:\n", "Problem name: Integer to Binary Example\n", "\n", "Minimize\n", " x^2*y + x^2 + 2*x\n", "\n", "Subject to\n", " Linear constraints (1)\n", " x + y <= 2 'c1'\n", "\n", " Integer variables (1)\n", " 0 <= x <= 3\n", "\n", " Binary variables (1)\n", " y\n", "\n", "\n", "Converted Problem:\n", "Problem name: Integer to Binary Example\n", "\n", "Minimize\n", " x@0^2*y + 4*x@0*x@1*y + 4*x@1^2*y + x@0^2 + 4*x@0*x@1 + 4*x@1^2 + 2*x@0\n", " + 4*x@1\n", "\n", "Subject to\n", " Linear constraints (1)\n", " x@0 + 2*x@1 + y <= 2 'c1'\n", "\n", " Binary variables (3)\n", " x@0 x@1 y\n", "\n" ] } ], "source": [ "from qiskit_addon_opt_mapper import OptimizationProblem\n", "from qiskit_addon_opt_mapper.converters import IntegerToBinary\n", "\n", "# Create an optimization problem with integer variables\n", "op = OptimizationProblem(\"Integer to Binary Example\")\n", "op.integer_var(name=\"x\", lowerbound=0, upperbound=3)\n", "op.binary_var(name=\"y\")\n", "\n", "op.minimize(linear={\"x\": 2}, quadratic={(\"x\", \"x\"): 1}, higher_order={3: {(\"x\", \"x\", \"y\"): 1}})\n", "op.linear_constraint(linear={\"x\": 1, \"y\": 1}, sense=\"LE\", rhs=2, name=\"c1\")\n", "print(\"Original Problem:\")\n", "print(op.prettyprint())\n", "# Convert integer variables to binary variables\n", "int_to_bin = IntegerToBinary()\n", "op_bin = int_to_bin.convert(op)\n", "print(\"\\nConverted Problem:\")\n", "print(op_bin.prettyprint())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Binary to Spin Conversion\n", "The `BinaryToSpin` converter transforms binary variables (0/1) into spin variables (-1/+1) using the relation $b = (1 - s)/2$, where $b$ is a binary variable and $s$ is a spin variable. This conversion is particularly useful in quantum computing contexts, where spin variables are often preferred." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Binary Problem:\n", "Problem name: Binary to Spin Example\n", "\n", "Minimize\n", " b1*b2 + b1 + b2\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " b1 b2\n", "\n", "\n", "Converted Spin Problem:\n", "Problem name: Binary to Spin Example\n", "\n", "Minimize\n", " 0.25*b1@spin*b2@spin - 0.75*b1@spin - 0.75*b2@spin + 1.25\n", "\n", "Subject to\n", " No constraints\n", "\n", " Spin variables (2)\n", " -1 <= b1@spin <= 1\n", " -1 <= b2@spin <= 1\n", "\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.converters import BinaryToSpin\n", "\n", "# Convert binary variables to spin variables\n", "op_bin = OptimizationProblem(\"Binary to Spin Example\")\n", "op_bin.binary_var(name=\"b1\")\n", "op_bin.binary_var(name=\"b2\")\n", "op_bin.minimize(linear={\"b1\": 1, \"b2\": 1}, quadratic={(\"b1\", \"b2\"): 1})\n", "print(\"Original Binary Problem:\")\n", "print(op_bin.prettyprint())\n", "\n", "# Convert binary variables to spin variables\n", "bin_to_spin = BinaryToSpin()\n", "op_spin = bin_to_spin.convert(op_bin)\n", "print(\"\\nConverted Spin Problem:\")\n", "print(op_spin.prettyprint())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Spin to Binary Conversion\n", "The `SpinToBinary` converter transforms spin variables (-1/+1) into binary variables (0/1) using the relation $s = 1 - 2b$, where $s$ is a spin variable and $b$ is a binary variable. This conversion is useful when an optimization problem needs to be expressed in terms of binary variables for certain algorithms or solvers." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Spin Problem:\n", "Problem name: Spin to Binary Example\n", "\n", "Minimize\n", " s1*s2 + s1 + s2\n", "\n", "Subject to\n", " No constraints\n", "\n", " Spin variables (2)\n", " -1 <= s1 <= 1\n", " -1 <= s2 <= 1\n", "\n", "\n", "Converted Binary Problem:\n", "Problem name: Spin to Binary Example\n", "\n", "Minimize\n", " 4*s1@bin*s2@bin - 4*s1@bin - 4*s2@bin + 3\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " s1@bin s2@bin\n", "\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.converters import SpinToBinary\n", "\n", "op_spin2 = OptimizationProblem(\"Spin to Binary Example\")\n", "op_spin2.spin_var(name=\"s1\")\n", "op_spin2.spin_var(name=\"s2\")\n", "op_spin2.minimize(linear={\"s1\": 1, \"s2\": 1}, quadratic={(\"s1\", \"s2\"): 1})\n", "print(\"Original Spin Problem:\")\n", "print(op_spin2.prettyprint())\n", "# Convert spin variables to binary variables\n", "spin_to_bin = SpinToBinary()\n", "op_bin2 = spin_to_bin.convert(op_spin2)\n", "print(\"\\nConverted Binary Problem:\")\n", "print(op_bin2.prettyprint())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Inequality to Equality Conversion\n", "The `InequalityToEquality` converter transforms inequality constraints into equality constraints by introducing slack variables. For example, an inequality constraint of the form:\n", "$ax + by \\leq c$\n", "is converted to an equality constraint:\n", "$ax + by + s = c$\n", "where $s$ is a slack variable that is constrained to be non-negative ($s \\geq 0$). This conversion allows the optimization problem to be expressed entirely in terms of equality constraints, which can be beneficial for certain optimization algorithms that require equality constraints." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Problem:\n", "Problem name: Inequality to Equality Example\n", "\n", "Minimize\n", " x + y\n", "\n", "Subject to\n", " Linear constraints (2)\n", " x + y <= 5 'c1'\n", " 10*x >= 3 'c2'\n", "\n", " Binary variables (2)\n", " x y\n", "\n", "\n", "Converted Problem:\n", "Problem name: Inequality to Equality Example\n", "\n", "Minimize\n", " x + y\n", "\n", "Subject to\n", " Linear constraints (2)\n", " c1@int_slack + x + y == 5 'c1'\n", " -c2@int_slack + 10*x == 3 'c2'\n", "\n", " Integer variables (2)\n", " 0 <= c1@int_slack <= 5\n", " 0 <= c2@int_slack <= 7\n", "\n", " Binary variables (2)\n", " x y\n", "\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.converters import InequalityToEquality\n", "\n", "# Create an optimization problem with an inequality constraint\n", "op2 = OptimizationProblem(\"Inequality to Equality Example\")\n", "op2.binary_var(name=\"x\")\n", "op2.binary_var(name=\"y\")\n", "op2.minimize(linear={\"x\": 1, \"y\": 1})\n", "op2.linear_constraint(linear={\"x\": 1, \"y\": 1}, sense=\"LE\", rhs=5, name=\"c1\")\n", "op2.linear_constraint(linear={\"x\": 10}, sense=\"GE\", rhs=3, name=\"c2\")\n", "print(\"Original Problem:\")\n", "print(op2.prettyprint())\n", "# Convert inequality constraints to equality constraints\n", "ineq_to_eq = InequalityToEquality()\n", "op_eq = ineq_to_eq.convert(op2)\n", "print(\"\\nConverted Problem:\")\n", "print(op_eq.prettyprint())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Equality to Penalty Conversion\n", "The `EqualityToPenalty` converter transforms equality constraints into penalty terms added to the objective function.\n", "\\begin{array}{}\n", "\\text { Equality constraint } & & \\text { Penalty term } \\\\\n", "ax + by = c & \\rightarrow & P(c - (ax + by))^2 \\\\\n", "\\end{array}\n", "where $P$ is a large positive/negative constant that penalizes deviations from the equality constraint (When the problem is a minimizing problem, $P$ should be a large positive constant. Conversely, when the problem is a maximizing problem, $P$ should be a large negative constant). This approach effectively incorporates the equality constraints into the objective function, allowing the optimization algorithm to focus on minimizing or maximizing the modified objective function while still respecting the original constraints.\n", "If $P$ is not specified, it is automatically set to a value larger than the sum of the absolute values of the coefficients in the objective function." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Problem:\n", "Problem name: Equality to Penalty Example\n", "\n", "Minimize\n", " 0\n", "\n", "Subject to\n", " Linear constraints (1)\n", " x + y == 3 'c1'\n", "\n", " Binary variables (2)\n", " x y\n", "\n", "\n", "Converted Problem:\n", "Problem name: \n", "\n", "Minimize\n", " 100000*x^2 + 200000*x*y + 100000*y^2 - 600000*x - 600000*y + 900000\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " x y\n", "\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.converters import EqualityToPenalty\n", "\n", "# Create an optimization problem with an equality constraint\n", "op3 = OptimizationProblem(\"Equality to Penalty Example\")\n", "op3.binary_var(name=\"x\")\n", "op3.binary_var(name=\"y\")\n", "op3.linear_constraint(linear={\"x\": 1, \"y\": 1}, sense=\"EQ\", rhs=3, name=\"c1\")\n", "print(\"Original Problem:\")\n", "print(op3.prettyprint())\n", "# Convert equality constraints to penalty terms in the objective function\n", "eq_to_penalty = EqualityToPenalty(penalty=1e5)\n", "op_penalty = eq_to_penalty.convert(op3)\n", "print(\"\\nConverted Problem:\")\n", "print(op_penalty.prettyprint())" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Converted Problem with Automatic Penalty:\n", "Problem name: \n", "\n", "Minimize\n", " x^2 + 2*x*y + y^2 - 6*x - 6*y + 9\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " x y\n", "\n" ] } ], "source": [ "# Automatic penalty value\n", "eq_to_penalty_auto = EqualityToPenalty()\n", "op_penalty_auto = eq_to_penalty_auto.convert(op3)\n", "print(\"\\nConverted Problem with Automatic Penalty:\")\n", "print(op_penalty_auto.prettyprint())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Linear Inequality to Penalty Conversion\n", "The `LinearInequalityToPenalty` converter transforms specific binary linear inequality constraints into penalty terms added to\n", "the objective function with a fewer number of additional variables compared to the `InequalityToEquality` converter followed by the `EqualityToPenalty` converter.\n", "\n", "\\begin{array}{}\n", "\\text { Inequality constraint } & & \\text { Penalty term } \\\\\n", "x \\leq y & \\rightarrow & P(x-x y) \\\\\n", "x \\geq y & \\rightarrow & P(y-x y) \\\\\n", "\\sum_{i=1}^n x_i \\leq 1, n \\geq 2 & \\rightarrow &\n", " P \\sum_{i, j : i < j} x_i x_j\\\\\n", "\\sum_{i=1}^n x_i \\geq n-1, n \\geq 2 & \\rightarrow &\n", " P \\sum_{i, j : i < j} (1 - x_i) (1 - x_j)\n", "\\end{array}\n", "\n", "*Note that x, y, z and `x_i` are binary variables, and P is a penalty factor,where the value of P is automatically determined or supplied by users.*" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Problem:\n", "Problem name: Linear Inequality to Penalty Example\n", "\n", "Minimize\n", " 0\n", "\n", "Subject to\n", " Linear constraints (1)\n", " x - y <= 0 'c1'\n", "\n", " Binary variables (2)\n", " x y\n", "\n", "\n", "Converted Problem:\n", "Problem name: Linear Inequality to Penalty Example\n", "\n", "Minimize\n", " -100000*x*y + 100000*x\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " x y\n", "\n" ] } ], "source": [ "# Linear Inequality to Penalty Conversion\n", "from qiskit_addon_opt_mapper.converters import LinearInequalityToPenalty\n", "\n", "# Create an optimization problem with a specific linear inequality constraint\n", "op4 = OptimizationProblem(\"Linear Inequality to Penalty Example\")\n", "op4.binary_var(name=\"x\")\n", "op4.binary_var(name=\"y\")\n", "op4.linear_constraint(linear={\"x\": 1, \"y\": -1}, sense=\"LE\", rhs=0, name=\"c1\") # x <= y\n", "print(\"Original Problem:\")\n", "print(op4.prettyprint())\n", "# Convert specific linear inequality constraints to penalty terms in the objective function\n", "lin_ineq_to_penalty = LinearInequalityToPenalty(penalty=1e5)\n", "op4_penalty = lin_ineq_to_penalty.convert(op4)\n", "print(\"\\nConverted Problem:\")\n", "print(op4_penalty.prettyprint())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Maximize to Minimize Conversion\n", "The `MaximizeToMinimize` converter transforms a maximization objective into a minimization objective by negating the coefficients of the objective function.\n", "\\begin{array}{}\n", "\\text { Maximization objective } & & \\text { Minimization objective } \\\\\n", "\\max (ax + by) & \\rightarrow & \\min - (ax + by)\n", "\\end{array}\n", "The `MinimizeToMaximize` converter performs the inverse operation, converting a minimization objective into a maximization objective by negating the coefficients of the objective function." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Problem:\n", "Problem name: Maximize to Minimize Example\n", "\n", "Maximize\n", " x + 2*y\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " x y\n", "\n", "\n", "Converted Problem:\n", "Problem name: Maximize to Minimize Example\n", "\n", "Minimize\n", " -x - 2*y\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " x y\n", "\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.converters import MaximizeToMinimize, MinimizeToMaximize\n", "\n", "# Create an optimization problem with a maximization objective\n", "op5 = OptimizationProblem(\"Maximize to Minimize Example\")\n", "op5.binary_var(name=\"x\")\n", "op5.binary_var(name=\"y\")\n", "op5.maximize(linear={\"x\": 1, \"y\": 2})\n", "print(\"Original Problem:\")\n", "print(op5.prettyprint())\n", "# Convert maximization objective to minimization objective\n", "max_to_min = MaximizeToMinimize()\n", "op5_min = max_to_min.convert(op5)\n", "print(\"\\nConverted Problem:\")\n", "print(op5_min.prettyprint())" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Re-converted Problem:\n", "Problem name: Maximize to Minimize Example\n", "\n", "Maximize\n", " x + 2*y\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (2)\n", " x y\n", "\n" ] } ], "source": [ "# Minimize to Maximize Conversion\n", "min_to_max = MinimizeToMaximize()\n", "op5_max = min_to_max.convert(op5_min)\n", "print(\"\\nRe-converted Problem:\")\n", "print(op5_max.prettyprint())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## QUBO Conversion\n", "The `OptimizationProblemToQubo` converter transforms an `OptimizationProblem` in quadratic format (quadratic objective function with linear constraints)\n", "into QUBO form by converting variables to binary and eliminating constraints. It combines several converters: `IntegerToBinary`, `SpinToBinary`, `InequalityToPenalty`, `InequalityToEquality`, `EqualityToPenalty`, and `MaximizeToMinimize`.\n", "The resulting QUBO problem can be directly mapped to an Ising Hamiltonian using the `to_ising()` function." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Problem:\n", "Problem name: Quadratic Program to QUBO Example\n", "\n", "Minimize\n", " x*y + 2*x\n", "\n", "Subject to\n", " Linear constraints (1)\n", " x + y <= 5 'c1'\n", "\n", " Integer variables (1)\n", " 0 <= x <= 3\n", "\n", " Binary variables (1)\n", " y\n", "\n", "\n", "Converted QUBO Problem:\n", "Problem name: \n", "\n", "Minimize\n", " 100000*c1@int_slack@0^2 + 400000*c1@int_slack@0*c1@int_slack@1\n", " + 400000*c1@int_slack@0*c1@int_slack@2 + 400000*c1@int_slack@1^2\n", " + 800000*c1@int_slack@1*c1@int_slack@2 + 400000*c1@int_slack@2^2\n", " + 200000*x@0*c1@int_slack@0 + 400000*x@0*c1@int_slack@1\n", " + 400000*x@0*c1@int_slack@2 + 100000*x@0^2 + 400000*x@0*x@1 + 200001*x@0*y\n", " + 400000*x@1*c1@int_slack@0 + 800000*x@1*c1@int_slack@1\n", " + 800000*x@1*c1@int_slack@2 + 400000*x@1^2 + 400002*x@1*y\n", " + 200000*y*c1@int_slack@0 + 400000*y*c1@int_slack@1 + 400000*y*c1@int_slack@2\n", " + 100000*y^2 - 1000000*c1@int_slack@0 - 2000000*c1@int_slack@1\n", " - 2000000*c1@int_slack@2 - 999998*x@0 - 1999996*x@1 - 1000000*y + 2500000\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (6)\n", " x@0 x@1 y c1@int_slack@0 c1@int_slack@1 c1@int_slack@2\n", "\n", "penalty: 100000.0\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.converters import OptimizationProblemToQubo\n", "\n", "# Create a optimization problem with various constraints\n", "op6 = OptimizationProblem(\"Quadratic Program to QUBO Example\")\n", "op6.integer_var(name=\"x\", lowerbound=0, upperbound=3)\n", "op6.binary_var(name=\"y\")\n", "op6.minimize(linear={\"x\": 2}, quadratic={(\"x\", \"y\"): 1})\n", "op6.linear_constraint(linear={\"x\": 1, \"y\": 1}, sense=\"LE\", rhs=5, name=\"c1\")\n", "print(\"Original Problem:\")\n", "print(op6.prettyprint())\n", "# Convert the optimization problem to QUBO format\n", "qubo_converter = OptimizationProblemToQubo(penalty=1e5)\n", "op6_qubo = qubo_converter.convert(op6)\n", "print(\"\\nConverted QUBO Problem:\")\n", "print(op6_qubo.prettyprint())\n", "print(f\"penalty: {qubo_converter.penalty}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## HUBO Conversion\n", "The `OptimizationProblemToHubo` converter transforms an `OptimizationProblem` into a HUBO format (higher-order objective function with no constraints) by converting variables to binary and eliminating constraints. It combines several converters: `IntegerToBinary`, `SpinToBinary`, `InequalityToPenalty`, `EqualityToPenalty`, and `MaximizeToMinimize`, while preserving higher-order terms in the objective function. The resulting HUBO problem can be directly mapped to an Ising Hamiltonian using the `to_ising()` function." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Original Problem:\n", "Problem name: Optimization Problem to HUBO Example\n", "\n", "Minimize\n", " x*y*z + x*y + 2*x\n", "\n", "Subject to\n", " Higher-order constraints (1)\n", " x*y*z == 2 'c1'\n", "\n", " Integer variables (1)\n", " 0 <= x <= 3\n", "\n", " Binary variables (2)\n", " y z\n", "\n", "\n", "Converted HUBO Problem:\n", "Problem name: \n", "\n", "Minimize\n", " 100000*x@0^2*y^2*z^2 + 400000*x@0*x@1*y^2*z^2 + 400000*x@1^2*y^2*z^2\n", " - 399999*x@0*y*z - 799998*x@1*y*z + x@0*y + 2*x@1*y + 2*x@0 + 4*x@1 + 400000\n", "\n", "Subject to\n", " No constraints\n", "\n", " Binary variables (4)\n", " x@0 x@1 y z\n", "\n", "penalty: 100000.0\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.converters import OptimizationProblemToHubo\n", "\n", "# Create an optimization problem with higher-order terms and constraints\n", "op7 = OptimizationProblem(\"Optimization Problem to HUBO Example\")\n", "op7.integer_var(name=\"x\", lowerbound=0, upperbound=3)\n", "op7.binary_var(name=\"y\")\n", "op7.binary_var(name=\"z\")\n", "\n", "op7.minimize(linear={\"x\": 2}, quadratic={(\"x\", \"y\"): 1}, higher_order={3: {(\"x\", \"y\", \"z\"): 1}})\n", "op7.higher_order_constraint(higher_order={3: {(\"x\", \"y\", \"z\"): 1}}, sense=\"EQ\", rhs=2, name=\"c1\")\n", "print(\"Original Problem:\")\n", "print(op7.prettyprint())\n", "# Convert the optimization problem to HUBO format\n", "hubo_converter = OptimizationProblemToHubo(penalty=1e5)\n", "op7_hubo = hubo_converter.convert(op7)\n", "print(\"\\nConverted HUBO Problem:\")\n", "print(op7_hubo.prettyprint())\n", "print(f\"penalty: {hubo_converter.penalty}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ising transformation\n", "Both QUBO and HUBO problems can be mapped to Ising Hamiltonians by the `to_ising()` function. In Optimization add-on, these are represented by the `qiskit.quantum_info.SparsePauliOp` object.\n", "In transforming to the Ising Hamiltonian, the binary variables are mapped to spin variables using the relation $b_i = (1 - Z_i)/2$, where $b_i$ is a binary variable and $Z_i$ is a pauli Z operator acting on the $i$-th qubit. The resulting Ising Hamiltonian can then be used in quantum algorithms to approximate the ground state." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Ising Hamiltonian from HUBO:\n", "Ising Hamiltonian: SparsePauliOp(['IIIZ', 'IIZI', 'IZIZ', 'IZII', 'IZZI', 'ZIII', 'ZIIZ', 'ZZII', 'ZZIZ', 'ZIZI', 'ZZZI', 'IIII', 'IIZZ', 'IZZZ', 'ZIZZ', 'ZZZZ'],\n", " coeffs=[ 12498.625+0.j, 24997.25 +0.j, -12499.625+0.j, 62498.875+0.j,\n", " -24999.25 +0.j, 62499.625+0.j, -12499.875+0.j, -62499.625+0.j,\n", " 12499.875+0.j, -24999.75 +0.j, 24999.75 +0.j, 73437.5 +0.j,\n", " 25000. +0.j, -25000. +0.j, -25000. +0.j, 25000. +0.j])\n", "Offset: 264066.625\n" ] } ], "source": [ "from qiskit_addon_opt_mapper.translators import to_ising\n", "\n", "ising_hubo, offset = to_ising(op7_hubo)\n", "print(\"\\nIsing Hamiltonian from HUBO:\")\n", "print(f\"Ising Hamiltonian: {ising_hubo}\")\n", "print(f\"Offset: {offset}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.13" } }, "nbformat": 4, "nbformat_minor": 4 }