{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"source": [
"#1. Inequality Constraints\n",
"In this notebook, we will learn how to handle inequality constraints in quantum annealing. Specifically, using the \"Capacity-Constrained Knapsack Problem\" as an example, we will implement the process of converting mathematical expressions (Hamiltonians) into Python code (QUBO matrices) step-by-step."
],
"metadata": {
"id": "xZT9aHSekdqh"
}
},
{
"cell_type": "markdown",
"source": [
"## 2. Problem Definition"
],
"metadata": {
"id": "tG54-QuslJ5H"
}
},
{
"cell_type": "markdown",
"source": [
"### 2.1. What is the Knapsack Problem?\n",
"\n",
"* There are $N$ items.\n",
"* Each item $i$ has an assigned weight $w_i$ and value $v_i$.\n",
"* The capacity of the knapsack is $C$. \n",
"**Objective:** To maximize the total value of the items placed in the knapsack such that their total weight does not exceed the capacity $C$."
],
"metadata": {
"id": "vEISGGl4lPxt"
}
},
{
"cell_type": "markdown",
"source": [
"### 2.2. Standard Formulation\n",
"\n",
"Mathematically, this problem is described as follows:\n",
"\n",
"$$\n",
"\\begin{aligned}\n",
"& \\text{Maximize} & & \\sum_{i=0}^{N-1} v_i x_i \\\\\n",
"& \\text{subject to} & & \\sum_{i=0}^{N-1} w_i x_i \\le C \\\\\n",
"& & & x_i \\in \\{0, 1\\}\n",
"\\end{aligned}\n",
"$$"
],
"metadata": {
"id": "vYQMKjgilUEO"
}
},
{
"cell_type": "markdown",
"source": [
"### 2.3. Explanation of Variables\n",
"\n",
"The meanings of the symbols appearing in this formula are as follows:\n",
"\n",
"| Symbol | Name | Description |\n",
"| :--- | :--- | :--- |\n",
"| **$N$** | Number of Items | The total number of items available. |\n",
"| **$i$** | Index | The item number ($0, 1, \\dots, N-1$). |\n",
"| **$x_i$** | **Decision Variable** | The variable we want to determine through optimization.
・$1$: **Include** item $i$ in the knapsack
・$0$: **Do not include** item $i$ in the knapsack |\n",
"| **$v_i$** | Value | The value of item $i$ (constant). We want to maximize the sum of these values. |\n",
"| **$w_i$** | Weight | The weight of item $i$ (constant). |\n",
"| **$C$** | Capacity | The maximum weight the knapsack can hold (constant). |"
],
"metadata": {
"id": "8N6pyL2xlX_U"
}
},
{
"cell_type": "markdown",
"source": [
"## 3. Mathematical Model Construction (Converting Inequality to Equality)"
],
"metadata": {
"id": "eXqWLxAAl8xW"
}
},
{
"cell_type": "markdown",
"source": [
"### 3.1. Objective Function\n",
"\"Maximizing value\" is equivalent to \"minimizing negative value\".\n",
"\n",
"$$H_{obj} = - \\sum_{i=0}^{N-1} v_i x_i$$"
],
"metadata": {
"id": "29DJp3QhmBhQ"
}
},
{
"cell_type": "markdown",
"source": [
"### 3.2. Constraints (Handling Inequalities)\n",
"The inequality constraint \"total weight $\\le C$\" is difficult to handle directly. Therefore, we introduce auxiliary variables $y_k$ representing that \"the actual weight placed in the knapsack is $k$ kg\" to convert it into an equality constraint.\n",
"\n",
"Here, $k$ takes values of $1, 2, \\dots, C$, and **exactly one of the auxiliary variables $y_1, y_2, \\dots, y_C$ must be 1 (One-hot)**.\n",
"\n",
"The constraints are expressed as the following two penalty terms:\n",
"\n",
"1. **One-hot Constraint ($H_{cost}^{(1)}$):** Exactly one of the auxiliary variables $y_k$ must be 1.\n",
"$$H_{cost}^{(1)} = \\lambda \\left( 1 - \\sum_{k=1}^{C} y_k\\right)^2$$\n",
"2. **Weight Matching Constraint ($H_{cost}^{(2)}$):** The weight $k$ indicated by the selected auxiliary variable matches the actual total weight of the items.\n",
"$$H_{cost}^{(2)} = \\lambda \\left( \\sum_{k=1}^{C} k y_k - \\sum_{i=0}^{N-1} w_i x_i \\right)^2$$\n",
"\n",
"($\\lambda$ is a large positive constant representing the strength of the penalty.)"
],
"metadata": {
"id": "dVeAsg2umE-e"
}
},
{
"cell_type": "markdown",
"source": [
"### 3.3. Total Hamiltonian\n",
"\n",
"The sum of these is the energy function that we ultimately need to minimize.\n",
"\n",
"$$H = H_{obj} + H_{cost}^{(1)} + H_{cost}^{(2)}$$\n",
"$$H = - \\sum_{i} v_i x_i + \\lambda \\left( 1 - \\sum_{k} y_k \\right)^2 + \\lambda \\left( \\sum_{k} k y_k - \\sum_{i} w_i x_i \\right)^2$$"
],
"metadata": {
"id": "XJqJv4PbmJv2"
}
},
{
"cell_type": "markdown",
"source": [
"## 4. Transformation of the Hamiltonian into QUBO Format\n",
"\n",
"To implement this in a program, we need to expand the Hamiltonian into a form consisting of products of variables (QUBO format), such as $x_i x_j$ and $y_k y_l$.\n",
"We expand this utilizing the property of binary variables, $x^2 = x$."
],
"metadata": {
"id": "RESgUAD7mLF_"
}
},
{
"cell_type": "markdown",
"source": [
"### 4.1. Objective Function $H_{obj}$\n",
"\n",
"Since this is already in a simple form, it directly becomes the diagonal elements $-v_i$.\n",
"$$H_{obj} = \\sum_{i} (-v_i) x_i$$"
],
"metadata": {
"id": "75QRiYU6mOHz"
}
},
{
"cell_type": "markdown",
"source": [
"### 4.2. Constraint Term 1 $H_{cost}^{(1)}$ (One-hot Constraint)\n",
"\n",
"Equation: $\\lambda ( 1 - \\sum_{k} y_k )^2$\n",
"\\begin{aligned}\n",
"H_{cost}^{(1)} &= \\lambda \\left( 1 - 2\\sum_{k} y_k + \\left(\\sum_{k} y_k\\right)^2 \\right) \\\\\n",
"&= \\lambda \\left( 1 - 2\\sum_{k} y_k + \\left( \\sum_{k} y_k^2 + \\sum_{k \\neq l} y_k y_l \\right) \\right) \\\\\n",
"&\\quad \\text{* Applying the binary variable property } y_k^2 = y_k \\\\\n",
"&= \\lambda \\left( 1 - 2\\sum_{k} y_k + \\sum_{k} y_k + 2\\sum_{k < l} y_k y_l \\right) \\\\\n",
"&= \\lambda \\left( 1 - \\sum_{k} y_k + 2\\sum_{k < l} y_k y_l \\right) \\\\\n",
"&\\simeq \\sum_{k} (-\\lambda) y_k + \\sum_{k < l} (2\\lambda) y_k y_l \\quad \\text{(Ignoring the constant term)}\n",
"\\end{aligned}"
],
"metadata": {
"id": "uCHpwNOImToa"
}
},
{
"cell_type": "markdown",
"source": [
"### 4.3. Constraint Term 2 $H_{cost}^{(2)}$ (Weight Matching Constraint)\n",
"\n",
"This is the most complex part. We will divide the equation into three parts and expand them.\n",
"$$H_{cost}^{(2)} = \\lambda \\left( \\underbrace{\\sum_{k=1}^{C} k y_k}_{A} - \\underbrace{\\sum_{i=0}^{N-1} w_i x_i}_{B} \\right)^2 = \\lambda(A^2 - 2AB + B^2)$$"
],
"metadata": {
"id": "NZ2Ccp-TmU0D"
}
},
{
"cell_type": "markdown",
"source": [
"#### 4.3.1.**Part A: Squared term of auxiliary variables ($A^2$)**\n",
"$$\n",
"\\begin{aligned}\n",
"\\lambda \\left(\\sum_{k} k y_k\\right)^2 &= \\lambda \\left( \\sum_{k} k^2 y_k + 2\\sum_{k < l} k l y_k y_l \\right)\n",
"\\end{aligned}\n",
"$$\n",
"Mapping to matrix $Q$:\n",
"* **$Q_{yy}$ (Diagonal):** $\\lambda k^2$\n",
"* **$Q_{yl}$ (Cross term $k=0.9.11 (from openjij)\n",
" Downloading dimod-0.12.21-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (4.0 kB)\n",
"Collecting jij-cimod<1.8.0,>=1.7.0 (from openjij)\n",
" Downloading jij_cimod-1.7.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (10.0 kB)\n",
"Requirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.3.3)\n",
"Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (0.12.1)\n",
"Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (4.61.1)\n",
"Requirement already satisfied: kiwisolver>=1.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (1.4.9)\n",
"Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (26.0)\n",
"Requirement already satisfied: pillow>=8 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (11.3.0)\n",
"Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (3.3.2)\n",
"Requirement already satisfied: python-dateutil>=2.7 in /usr/local/lib/python3.12/dist-packages (from matplotlib) (2.9.0.post0)\n",
"Collecting scipy<1.16,>=1.5.4 (from jij-cimod<1.8.0,>=1.7.0->openjij)\n",
" Downloading scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (61 kB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m62.0/62.0 kB\u001b[0m \u001b[31m3.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hRequirement already satisfied: six>=1.5 in /usr/local/lib/python3.12/dist-packages (from python-dateutil>=2.7->matplotlib) (1.17.0)\n",
"Downloading openjij-0.11.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (11.9 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11.9/11.9 MB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hDownloading dimod-0.12.21-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (8.9 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m8.9/8.9 MB\u001b[0m \u001b[31m8.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hDownloading jij_cimod-1.7.3-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (11.6 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m11.6/11.6 MB\u001b[0m \u001b[31m6.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hDownloading scipy-1.15.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (37.3 MB)\n",
"\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m37.3/37.3 MB\u001b[0m \u001b[31m15.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
"\u001b[?25hInstalling collected packages: scipy, dimod, jij-cimod, openjij\n",
" Attempting uninstall: scipy\n",
" Found existing installation: scipy 1.16.3\n",
" Uninstalling scipy-1.16.3:\n",
" Successfully uninstalled scipy-1.16.3\n",
"Successfully installed dimod-0.12.21 jij-cimod-1.7.3 openjij-0.11.6 scipy-1.15.3\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"### 5.2. Importing Libraries"
],
"metadata": {
"id": "lckqH1AooHEl"
}
},
{
"cell_type": "code",
"source": [
"import numpy as np\n",
"import openjij as oj"
],
"metadata": {
"id": "-Qsv7rexoBuL"
},
"execution_count": 2,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### 5.3. Problem **Setup**"
],
"metadata": {
"id": "qnsAO1wDoMX7"
}
},
{
"cell_type": "code",
"source": [
"# ==========================================\n",
"# Problem Setup\n",
"# ==========================================\n",
"# Define the list of items.\n",
"# Each dictionary represents one item. The keys mean the following:\n",
"# 'weight': w_i in the formula (weight)\n",
"# 'value': v_i in the formula (value)\n",
"items = [\n",
" {'weight': 2, 'value': 3},\n",
" {'weight': 3, 'value': 4},\n",
" {'weight': 4, 'value': 5},\n",
" {'weight': 5, 'value': 8}, # Heavy (5kg) but high value (8). Choosing this is the key.\n",
" {'weight': 1, 'value': 1}\n",
"]\n",
"\n",
"# For easier calculation, separate weights and values into distinct lists.\n",
"# This allows accessing the i-th weight via weights[i] and the i-th value via values[i].\n",
"weights = [item['weight'] for item in items]\n",
"values = [item['value'] for item in items]\n",
"\n",
"# ==========================================\n",
"# Definition of Constants and Parameters\n",
"# ==========================================\n",
"N = len(items) # Total number of items (N in the formula)\n",
" # -> This means item variables x_0 ... x_{N-1} are required.\n",
"\n",
"C = 7 # Capacity limit of the knapsack (C in the formula)\n",
" # -> Total weight must be less than or equal to this (Σw_i x_i <= C).\n",
"\n",
"# Penalty coefficient (λ: Lambda in the formula)\n",
"# The strength of the penalty imposed when constraints (capacity overflow or One-hot violation) are broken.\n",
"# If this value is too small, the solver might decide \"it's more profitable to include high-value items even with the penalty,\"\n",
"# resulting in a solution that violates the rules.\n",
"# Therefore, we set a value sufficiently larger than the item values (here, 100.0).\n",
"LAMBDA = 100.0\n",
"\n",
"# Display the setup for confirmation\n",
"print(f\"Items (Weight, Value): {list(zip(weights, values))}\")\n",
"print(f\"Capacity: {C}\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "7joj3DxToJ-L",
"outputId": "6ad02ca7-2f78-4912-fc3b-e322c1bc1034"
},
"execution_count": 4,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Items (Weight, Value): [(2, 3), (3, 4), (4, 5), (5, 8), (1, 1)]\n",
"Capacity: 7\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"### 5.4. Creating the QUBO Matrix"
],
"metadata": {
"id": "ZVMDy-J7pHjg"
}
},
{
"cell_type": "code",
"source": [
"# ==========================================\n",
"# QUBO Matrix Initialization (Zero Matrix)\n",
"# ==========================================\n",
"# Create a blank (N+C) x (N+C) matrix\n",
"Q = np.zeros((N+C, N+C))\n",
"\n",
"# --- Utility functions for index manipulation ---\n",
"def get_q_idx(i):\n",
" \"\"\"Index in the matrix for item i (0 to N-1)\"\"\"\n",
" return i\n",
"\n",
"def get_y_idx(k):\n",
" \"\"\"Index in the matrix for auxiliary variable y_k (k=1 to C)\"\"\"\n",
" # Follows the item variables. Since k starts at 1, subtract 1 to make it 0-indexed.\n",
" return N + (k - 1)\n",
"\n",
"# ==========================================\n",
"# Embedding into the QUBO Matrix\n",
"# ==========================================\n",
"\n",
"# ------------------------------------------------\n",
"# (A) Objective Function: Maximize value (Minimize negative value)\n",
"# ------------------------------------------------\n",
"for i in range(N):\n",
" idx = get_q_idx(i)\n",
" v = items[i]['value']\n",
" # Add -v to the diagonal component\n",
" Q[idx, idx] += -1 * v\n",
"\n",
"# ------------------------------------------------\n",
"# (B) Constraint 1: Exactly one auxiliary variable y must be 1 (One-hot)\n",
"# Formula: lambda * (1 - sum(y))^2\n",
"# Expansion -> lambda * ( sum(y^2) + sum(y_i*y_j) - 2sum(y) ) + constant\n",
"# ------------------------------------------------\n",
"for k1 in range(1, C + 1):\n",
" idx1 = get_y_idx(k1)\n",
"\n",
" # 1. Linear term: -2 * lambda * y_k\n",
" Q[idx1, idx1] += -2 * LAMBDA\n",
"\n",
" # 2. Squared term diagonal component: + lambda * y_k^2 (= y_k)\n",
" Q[idx1, idx1] += LAMBDA\n",
"\n",
" # 3. Squared term cross component: + 2 * lambda * y_k1 * y_k2\n",
" for k2 in range(k1 + 1, C + 1):\n",
" idx2 = get_y_idx(k2)\n",
" Q[idx1, idx2] += 2 * LAMBDA\n",
"\n",
"# ------------------------------------------------\n",
"# (C) Constraint 2: Match the total weights\n",
"# Formula: lambda * ( sum(k*y) - sum(w*q) )^2\n",
"# Expansion -> lambda * ( A^2 - 2AB + B^2 )\n",
"# A = sum(k*y), B = sum(w*q)\n",
"# ------------------------------------------------\n",
"\n",
"# --- Part 1: A^2 (Product of auxiliary variables) ---\n",
"# (sum k*y)^2 = sum k^2*y + sum 2*k1*k2*y1*y2\n",
"for k1 in range(1, C + 1):\n",
" idx1 = get_y_idx(k1)\n",
" # Diagonal component (k^2)\n",
" Q[idx1, idx1] += LAMBDA * (k1 ** 2)\n",
"\n",
" # Cross component (2 * k1 * k2)\n",
" for k2 in range(k1 + 1, C + 1):\n",
" idx2 = get_y_idx(k2)\n",
" Q[idx1, idx2] += LAMBDA * 2 * k1 * k2\n",
"\n",
"# --- Part 2: B^2 (Product of item variables) ---\n",
"# (sum w*q)^2 = sum w^2*q + sum 2*w1*w2*q1*q2\n",
"for i1 in range(N):\n",
" idx1 = get_q_idx(i1)\n",
" w1 = items[i1]['weight']\n",
" # Diagonal component (w^2)\n",
" Q[idx1, idx1] += LAMBDA * (w1 ** 2)\n",
"\n",
" # Cross component (2 * w1 * w2)\n",
" for i2 in range(i1 + 1, N):\n",
" idx2 = get_q_idx(i2)\n",
" w2 = items[i2]['weight']\n",
" Q[idx1, idx2] += LAMBDA * 2 * w1 * w2\n",
"\n",
"# --- Part 3: -2AB (Product of item and auxiliary variables) ---\n",
"# -2 * sum(k*y) * sum(w*q)\n",
"for k in range(1, C + 1):\n",
" idx_y = get_y_idx(k)\n",
" for i in range(N):\n",
" idx_q = get_q_idx(i)\n",
" w = items[i]['weight']\n",
"\n",
" # Coefficient: -2 * lambda * k * w\n",
" coeff = -2 * LAMBDA * k * w\n",
"\n",
" # Process to place in the upper triangular part of the matrix (row < col)\n",
" if idx_y < idx_q:\n",
" Q[idx_y, idx_q] += coeff\n",
" else:\n",
" Q[idx_q, idx_y] += coeff"
],
"metadata": {
"id": "f4WFG1CioQ77"
},
"execution_count": 7,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### 5.5. Solving with OpenJij"
],
"metadata": {
"id": "9ZNRHZcxpqN3"
}
},
{
"cell_type": "code",
"source": [
"# ==========================================\n",
"# Solving with OpenJij\n",
"# ==========================================\n",
"print(\"Calculating optimization...\")\n",
"sampler = oj.SQASampler()\n",
"# num_reads: Number of calculations (higher means more stable)\n",
"response = sampler.sample_qubo(Q, num_reads=1000)\n",
"\n",
"# Getting the best solution\n",
"sample = response.first.sample\n",
"\n",
"# ==========================================\n",
"# Displaying the results\n",
"# ==========================================\n",
"print(\"\\n\" + \"=\"*30)\n",
"print(\" Optimization Results \")\n",
"print(\"=\"*30)\n",
"\n",
"total_w = 0\n",
"total_v = 0\n",
"active_y = 0\n",
"\n",
"# --- Checking the items ---\n",
"print(\"[Selected Items]\")\n",
"for i in range(N):\n",
" idx = get_q_idx(i)\n",
" if sample[idx] == 1:\n",
" item = items[i]\n",
" print(f\" ID:{i} (Weight:{item['weight']}, Value:{item['value']})\")\n",
" total_w += item['weight']\n",
" total_v += item['value']\n",
"\n",
"# --- Checking the auxiliary variables ---\n",
"for k in range(1, C + 1):\n",
" idx = get_y_idx(k)\n",
" if sample[idx] == 1:\n",
" active_y = k\n",
"\n",
"print(\"-\" * 30)\n",
"print(f\"Total Value: {total_v}\")\n",
"print(f\"Total Weight: {total_w} / Capacity {C}\")\n",
"print(f\"Auxiliary Variable (Target Weight): {active_y}\")\n",
"\n",
"if total_w <= C and total_w == active_y:\n",
" print(\">>> Success: Optimal solution satisfying the constraints.\")\n",
"else:\n",
" print(\">>> Failure: Constraint violation occurred (possible lack of penalty).\")"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Vxh4dS0ioXgz",
"outputId": "d7483a2b-0ffb-44b2-9ace-13aadf5dfb92"
},
"execution_count": 12,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Calculating optimization...\n",
"\n",
"==============================\n",
" Optimization Results \n",
"==============================\n",
"[Selected Items]\n",
" ID:0 (Weight:2, Value:3)\n",
" ID:3 (Weight:5, Value:8)\n",
"------------------------------\n",
"Total Value: 11\n",
"Total Weight: 7 / Capacity 7\n",
"Auxiliary Variable (Target Weight): 7\n",
">>> Success: Optimal solution satisfying the constraints.\n"
]
}
]
},
{
"cell_type": "markdown",
"source": [
"### 5.6. Validity of the Solution\n",
"\n",
"First, let's verify if the constraints are satisfied.\n",
"* **Selected items:** ID:0 (2kg) and ID:3 (5kg)\n",
"* **Total weight:** 2 + 5 = 7 kg\n",
"* **Capacity limit:** $C$ = 7 kg\n",
"\n",
"The total weight does not exceed the capacity limit ($\\le$ 7).\n",
"Furthermore, please pay attention to the \"Auxiliary Variable (Target Weight): 7\" in the output. This means the annealing machine determined that \"the total weight of the items will be 7kg\" and correctly set the corresponding slack variable $y_7$ to 1.\n",
"The weight of the items and the auxiliary variable are perfectly synchronized, which is evidence that the mathematical model ($H_{cost}^{(2)}$) functioned correctly."
],
"metadata": {
"id": "qnIZq88Lp6HB"
}
},
{
"cell_type": "markdown",
"source": [
"### 5.7. Confirmation of Optimality\n",
"\n",
"Is this really the best combination (the optimal solution)? Let's compare it with other combinations.\n",
"\n",
"* **Pattern A (Current solution):**\n",
" * Item 0 (2kg, Value 3) + Item 3 (5kg, Value 8)\n",
" * $\\to$ Weight 7kg, **Value 11**\n",
"* **Pattern B (Another combination example):**\n",
" * Item 1 (3kg, Value 4) + Item 2 (4kg, Value 5)\n",
" * $\\to$ Weight 7kg, **Value 9**\n",
"* **Pattern C (Many light items):**\n",
" * Item 0 + Item 1 + Item 4\n",
" * $\\to$ Weight 6kg, **Value 8**\n",
"\n",
"The annealing machine has correctly searched for the combination that maximizes the value, rather than just satisfying the weight constraint."
],
"metadata": {
"id": "rt-x6oOlp9I4"
}
}
]
}