{"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"collapsed_sections":["9zppgpzQNJk2"],"authorship_tag":"ABX9TyNKBfdj4xiOmYOnt419tpc4"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"markdown","source":["# Simulated Annealing Tutorial ーEquality Constraintsー\n","\n","This notebook explains how to use equality constraints.\n","To approach this topic, we will examine the portfolio optimization problem and provide sample code."],"metadata":{"id":"sQ-e-VhcSygM"}},{"cell_type":"markdown","source":["## Preparation"],"metadata":{"id":"qKlFVtKN8eCP"}},{"cell_type":"code","source":["!pip install openjij\n","!pip install pyqubo"],"metadata":{"id":"tlQ6vJGPTAl6","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1771827347474,"user_tz":-540,"elapsed":10060,"user":{"displayName":"沖澤孝之介","userId":"02718127576258174876"}},"outputId":"cb340b92-5dd3-4167-a365-3e01aee8723a"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Requirement already satisfied: openjij in /usr/local/lib/python3.12/dist-packages (0.11.6)\n","Requirement already satisfied: numpy<2.4.0,>=1.19.3 in /usr/local/lib/python3.12/dist-packages (from openjij) (2.0.2)\n","Requirement already satisfied: dimod<0.13.0,>=0.9.11 in /usr/local/lib/python3.12/dist-packages (from openjij) (0.12.21)\n","Requirement already satisfied: jij-cimod<1.8.0,>=1.7.0 in /usr/local/lib/python3.12/dist-packages (from openjij) (1.7.3)\n","Requirement already satisfied: scipy<1.16,>=1.5.4 in /usr/local/lib/python3.12/dist-packages (from jij-cimod<1.8.0,>=1.7.0->openjij) (1.15.3)\n","Requirement already satisfied: pyqubo in /usr/local/lib/python3.12/dist-packages (1.5.0)\n","Requirement already satisfied: numpy>=1.17.3 in /usr/local/lib/python3.12/dist-packages (from pyqubo) (2.0.2)\n","Requirement already satisfied: dimod<0.13,>=0.9.14 in /usr/local/lib/python3.12/dist-packages (from pyqubo) (0.12.21)\n","Requirement already satisfied: dwave-neal>=0.5.7 in /usr/local/lib/python3.12/dist-packages (from pyqubo) (0.6.0)\n","Requirement already satisfied: Deprecated>=1.2.12 in /usr/local/lib/python3.12/dist-packages (from pyqubo) (1.3.1)\n","Requirement already satisfied: six>=1.15.0 in /usr/local/lib/python3.12/dist-packages (from pyqubo) (1.17.0)\n","Requirement already satisfied: wrapt<3,>=1.10 in /usr/local/lib/python3.12/dist-packages (from Deprecated>=1.2.12->pyqubo) (2.1.1)\n","Requirement already satisfied: dwave-samplers<2.0.0,>=1.0.0 in /usr/local/lib/python3.12/dist-packages (from dwave-neal>=0.5.7->pyqubo) (1.7.0)\n","Requirement already satisfied: networkx>=3.0 in /usr/local/lib/python3.12/dist-packages (from dwave-samplers<2.0.0,>=1.0.0->dwave-neal>=0.5.7->pyqubo) (3.6.1)\n"]}]},{"cell_type":"code","source":["import numpy as np"],"metadata":{"id":"qNor_vi1TDcp"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["import openjij as oj"],"metadata":{"id":"48rYrxfmTRip"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["import matplotlib.pyplot as plt"],"metadata":{"id":"0ajpdRIYlk20"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["from pyqubo import Array, Constraint, Placeholder"],"metadata":{"id":"WO9B8mdR08WR"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["## Define the problem"],"metadata":{"id":"VPd-4sQ184zY"}},{"cell_type":"markdown","source":["Portfolio optimization involves finding the optimal combination of stocks for investment, taking into account both risk and return.\n","\n","To simplify the formulation, we consider a situation where we wish to diversify investments across $M$ stocks selected from $N$ stocks, choosing only whether to buy or not buy each stock.\n","\n","Let $C_1, \\dots, C_N$ denote the returns of each stock. This problem can be formulated as follows:\n","\n","$$\n","{\\text{min}} \\,\\,\\,( \\sum_{i = 1}^N C_ix_i - \\lambda (\\sum_{i = 1}^N C_i - M)^2)\n","$$\n","\n","Here, the second term is called the penalty term.\n","It is expressing the equality constraint that the number of stocks to buy is M in a form suitable for QUBO formulation."],"metadata":{"id":"kDs8uPp-87s7"}},{"cell_type":"code","source":["N = 10 # problem size\n","C_min = 1 # minimum return\n","C_max = 10 # maximum return\n","C = np.random.randint(low=C_min, high=C_max, size=N)\n","M = 4 # equality costraint\n","\n","print(f\"{C=}\")"],"metadata":{"id":"LRYp04278Zuc","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1771831472676,"user_tz":-540,"elapsed":47,"user":{"displayName":"沖澤孝之介","userId":"02718127576258174876"}},"outputId":"7873914e-8cfe-44b6-a915-de2451e5fc44"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["C=array([3, 8, 6, 4, 4])\n"]}]},{"cell_type":"markdown","source":["## Formulate"],"metadata":{"id":"jPCPoWZE8mA7"}},{"cell_type":"markdown","source":["We use pyqubo(https://pyqubo.readthedocs.io/en/latest/) to construct the above formulation.\n","(You may use other methods.)"],"metadata":{"id":"7_KN4tYepsBd"}},{"cell_type":"code","source":["# variable values\n","x = Array.create('',shape=N, vartype='BINARY')\n","\n","# objective function\n","H_1 = -sum(C[i]*x[i] for i in range (N))\n","\n","# equality costraint\n","H_2 = Constraint((sum(x)-M)**2, \"lambda\")\n","\n","# Hamiltonian\n","H = H_1 + Placeholder(\"lambda\")*H_2\n","\n","# compile to a model\n","model = H.compile()\n","\n","# specify the coefficient lambda and convert it to QUBO\n","feed_dict = {\"lambda\": 20}\n","qubo_dict, offset = model.to_qubo(feed_dict=feed_dict)"],"metadata":{"id":"z3R87_Ma4QHQ"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["print(x)\n","print(qubo_dict)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/"},"id":"rwQ7IRfuJKli","executionInfo":{"status":"ok","timestamp":1771831817578,"user_tz":-540,"elapsed":6,"user":{"displayName":"沖澤孝之介","userId":"02718127576258174876"}},"outputId":"f26fc266-ed30-4ba4-e1e4-a00eaf6e7285"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Array([Binary('[0]'), Binary('[1]'), Binary('[2]'), Binary('[3]'), Binary('[4]')])\n","{('[1]', '[1]'): -68.0, ('[4]', '[0]'): 40.0, ('[0]', '[0]'): -63.0, ('[3]', '[3]'): -64.0, ('[4]', '[2]'): 40.0, ('[4]', '[1]'): 40.0, ('[4]', '[3]'): 40.0, ('[2]', '[2]'): -66.0, ('[3]', '[2]'): 40.0, ('[1]', '[0]'): 40.0, ('[3]', '[0]'): 40.0, ('[2]', '[1]'): 40.0, ('[3]', '[1]'): 40.0, ('[2]', '[0]'): 40.0, ('[4]', '[4]'): -64.0}\n"]}]},{"cell_type":"code","source":["import re\n","# Show QUBO heatmap\n","QUBO = np.zeros((N,N))\n","for (x_i,x_j) in qubo_dict.keys():\n"," i = int(re.findall(r'\\d+', x_i)[0])\n"," j = int(re.findall(r'\\d+', x_j)[0])\n"," QUBO[i][j] = qubo_dict[(x_i,x_j)]\n","\n","plt.imshow(QUBO)\n","plt.colorbar()\n","plt.title('pyqubo matrix')\n","plt.show()"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":452},"id":"h1-fSVqIIJvQ","executionInfo":{"status":"ok","timestamp":1771831819452,"user_tz":-540,"elapsed":246,"user":{"displayName":"沖澤孝之介","userId":"02718127576258174876"}},"outputId":"751ff521-b7b3-42b7-ba31-79d3a6efd25f"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/plain":["
"],"image/png":"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m/rBD34QlMB69OihM2fO6NKlS0Gfd/To0Trn7NChgy5cuFBn/FplfLMYJemPf/xjIMZr1xdf71xHjhxR586dAy36UNiyZYs8Ho/efvttPfbYY3rwwQeVnp5+3aTblJdYLV26VJ999plWrlyp48ePa/HixU322QBujESNZpWfnx/0+rnnnpMkjR07Nmh8ypQpOn/+vB577DFdunRJ//zP/xz0/oMPPqirV68GXRrk9XoDn/dVt99+u44cOaKzZ88Gxj755BP97ne/u26Mb775pk6dOhV4vW/fPn300UeBGG+77TYNGjRIv/jFL4L+ADh06JDee+89Pfjgg1/3E9h27Q+WaxW25G93FxYW1tm3bdu21/0jpaE++ugjrVy5UvPnz9fChQv1ox/9SM8//7yKiopsfzaAr8flWWhWx48f10MPPaQHHnhAxcXFevXVVzV58uQ6105/61vf0oABA/T666/rzjvv1ODBg4PeHz9+vIYNG6bFixfrxIkT6tevn379619fd3720Ucf1apVq5SRkaHp06ersrJSL774ovr376/q6uo6+/fp00f33HOPZs2aJY/HozVr1qhTp0768Y9/HNhnxYoVGjt2rNLS0jR9+vTA5Vlut1vLli1rmh/rBsaMGaOYmBiNHz8+8IfMSy+9pISEBJ05cyZo39TUVBUUFOipp55Snz59lJCQoNGjRzfofJcvX1ZmZqa++c1v6umnn5YkPfnkk9qyZYumTZumgwcPhrSDALR44V10jpbi2uVZn376qfXd737Xio+Ptzp06GDNmTPH+uKLL657zLPPPmtJsp555pnrvv/Xv/7VmjJliuVyuSy3221NmTLF+u///u86l2dZlmW9+uqrVu/eva2YmBhr0KBB1vbt2294edaKFSusf//3f7eSk5Mtp9NpDR8+PHD52Fe9//771rBhw6y4uDjL5XJZ48ePtz799NOb/hbXLs96/fXXg8avXRa1f//+6/52Z8+eDYy9/fbbVkpKihUbG2v17NnT+ulPf2q98sordS6rKi8vt8aNG2fFx8dbkgKXat3oXF9979rnLFiwwIqOjrY++uijoP0+/vhjq1WrVtasWbNu+p0BNJ7Dsr7SPwNCZNmyZXryySd19uxZde7cuV7HrF27VgsWLNCJEyfqfRnQiRMn1KtXLxUWFiorK8tGxABgBuaoYSTLsvTyyy9r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\n"},"metadata":{}}]},{"cell_type":"markdown","source":["## Solve the problem with SA"],"metadata":{"id":"Lr9wjCOr8vzU"}},{"cell_type":"code","source":["# Conduct Simulated Annealing\n","num_reads = 300\n","num_sweeps = 1000\n","sampler = oj.SASampler()\n","sampleset = sampler.sample_qubo(QUBO, num_reads=num_reads, num_sweeps=num_sweeps)"],"metadata":{"id":"PZ3CfPVLltGx"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# Obtain the solution of minimum objective value\n","x_star = np.array([sampleset.first.sample[i] for i in range(N)])"],"metadata":{"id":"S7QUt-9jt3Ji"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["Finally, let's check the results."],"metadata":{"id":"x8Az5gnFMjwy"}},{"cell_type":"code","source":["# See the result\n","print(f\"{x_star=}\")\n","print(f\"{C@x_star=}\")"],"metadata":{"id":"URnsFJJjywd_","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1771832087300,"user_tz":-540,"elapsed":21,"user":{"displayName":"沖澤孝之介","userId":"02718127576258174876"}},"outputId":"2fbc4738-d8b5-43da-dfbc-a718f7a5ed0c"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["x_star=array([0, 1, 1, 0, 0], dtype=int8)\n","C@x_star=np.int64(14)\n"]}]},{"cell_type":"markdown","source":["If the optimul solution breaks the equality_constraints, you should increase lambda value."],"metadata":{"id":"NVlQAZDCae7e"}},{"cell_type":"markdown","source":["# [Step up] How to represent discrete values\n","\n","When diversifying investments to account for risk, no one thinks only two options: buy or not. Moving forward, we will focus on how to represent discrete values on QUBO."],"metadata":{"id":"I9euIKVwnhiC"}},{"cell_type":"markdown","source":[],"metadata":{"id":"zhhrax4pnirX"}}]}