From 86a696d9f30f8c55922fd36e139847f00704a6ad Mon Sep 17 00:00:00 2001 From: Preetham Tikkireddi Date: Sat, 3 Feb 2024 14:14:59 -0600 Subject: [PATCH 01/12] requirements and gitignore --- .gitignore | 1 + requirements.txt | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 .gitignore create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b694934 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.venv \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..be9f9d2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +pandas +numpy +pyqubo +dimod +dwave-neal +scipy +matplotlib From 4874446b0dc34004f3480fcd8114c0d923e32f01 Mon Sep 17 00:00:00 2001 From: Preetham Tikkireddi Date: Sat, 3 Feb 2024 15:21:56 -0600 Subject: [PATCH 02/12] ex1 done --- .../moodys_challenge-checkpoint.ipynb | 879 ++++++++++++++++++ moodys_challenge.ipynb | 28 +- requirements.txt | 2 + 3 files changed, 906 insertions(+), 3 deletions(-) create mode 100644 .ipynb_checkpoints/moodys_challenge-checkpoint.ipynb diff --git a/.ipynb_checkpoints/moodys_challenge-checkpoint.ipynb b/.ipynb_checkpoints/moodys_challenge-checkpoint.ipynb new file mode 100644 index 0000000..d0cc91e --- /dev/null +++ b/.ipynb_checkpoints/moodys_challenge-checkpoint.ipynb @@ -0,0 +1,879 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "de7fe4be-dd2d-4d8c-9358-5ab6a636496e", + "metadata": {}, + "source": [ + "# The path to Quantum in production in the financial industry" + ] + }, + { + "cell_type": "markdown", + "id": "266aceea-015c-4c8b-a75e-7e9e74c47f33", + "metadata": {}, + "source": [ + "## How could quantum avoid the drawbacks of classical optimization algorithms?\n" + ] + }, + { + "cell_type": "markdown", + "id": "6c89cba0-4047-4b23-b949-baa20f67fae5", + "metadata": {}, + "source": [ + "## Learning objectives of the challenge" + ] + }, + { + "cell_type": "markdown", + "id": "7fb51a43-6f42-4077-a894-38c874c61721", + "metadata": {}, + "source": [ + "**1.** Leverage quantum computing to try to avoid the drawbacks of classical optimization algorithms for portfolio optimization in the financial industry. What are the most promising problems and the corresponding techniques to solve them?
\n", + "**2.** What are the main bottlenecks/steps to solve financial optimization problems with quantum? What are the proposals in the literature to overcome them? Inclusion of equality and inequality constraints in optimization problems.
\n", + "**3.** Mapping a classical portfolio optimization problem to a quantum one.
\n", + "**4.** Think about resource estimation, can we do something useful with near term devices? How far are we from quantum advantage? How do we translate hardware roadmaps into utility timelines?
\n", + "**5.** Use of simulated annealing and other quantum computing techniques to find the solution of the problem. " + ] + }, + { + "cell_type": "markdown", + "id": "85d339f8-0a2d-4c84-88d2-ae2f5d7e7597", + "metadata": {}, + "source": [ + "## The challenge" + ] + }, + { + "cell_type": "markdown", + "id": "ddf18fd5", + "metadata": {}, + "source": [ + "### Portfolio optimization in the financial industry\n", + "\n", + "\n", + "Portfolio optimization is a formal mathematical approach to making investment decisions across a collection of financial instruments or assets. In 1952, Harry Markowitz introduced Modern Portfolio Theory (MPT). MPT introduced the notion that the diversification of a portfolio can inherently decrease the risk of a portfolio. Simply put, this meant that investors could increase their returns while also reducing their risk. Markowitz’s work on MPT was groundbreaking in the world of asset allocation, eventually earning him a Nobel prize for his work in 1990.\n", + "\n", + "\n", + "The behaviour of a portfolio can be quite different from the behaviour of\n", + "individual components of the portfolio. The risk of a properly constructed\n", + "portfolio from equities in leading markets could be half the sum of the risks of\n", + "individual assets in the portfolio. This is due to complex correlation patterns\n", + "between individual assets or equities. A good optimizer can exploit the\n", + "correlations, the expected returns, the risk (variance) and user constraints\n", + "to obtain an optimized portfolio.\n", + "\n", + "Portfolio optimization is often called **mean-variance (MV)** optimization.\n", + "The term mean refers to the *mean or the expected return* of the investment\n", + "and the *variance* is the measure of the risk associated with the portfolio.\n", + "\n", + "![image](data:image/png;base64,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)\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "In this challenge, we consider an alternative Markowitz’s mean–variance model in which the variance is replaced with an industry standard risk measure, Value-at-Risk (VaR), in order to better assess market risk exposure associated with financial and commodity asset price fluctuations.\n", + "\n", + "\n", + " VaR is defined as the maximum dollar amount expected to be lost over a given time horizon, at a pre-defined confidence level. For example, if the 95% one-month VAR is 1 million dollars, there is 95% confidence that over the next month the portfolio will not lose more than 1 million dollars. Realistic portfolio optimization in the mean-VaR framework is a challenging problem since it leads to a *non-convex NP-hard problem* which is computationally intractable. In fact, minimizing a nonparametric VaR measure is a complex task due to the non-smooth objective function landscape with many local minima. When more dimensions and trading constraints are added to the problem, the complexity of the problem increases. Hence, a good candidate to becnhmark quantum optimization heuristics.\n", + "\n", + "In the MV model, risk is defined by a dispersion parameter and it is assumed that returns are normally or elliptically distributed. However, the distributions of returns are asymmetric and usually have excess kurtosis in practice. Variance as a risk measure has thus been widely criticized by practitioners due to its symmetrical measure which equally weights desirable positive returns and undesirable negative ones. In fact, Markowitz recognized the inefficiencies embedded in the mean–variance approach. As a result, several extensions\n", + "and modifications of the basic Markowitz model reflecting real-world constraints have been developed.\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "c898b22a-1ee3-4cf5-af66-0c9ff99ecaa8", + "metadata": {}, + "source": [ + "### Problem Statement -- The Mean-Variance-VaR model" + ] + }, + { + "cell_type": "markdown", + "id": "cfe38b05-e39a-4d01-a1d6-b6fafcec3db3", + "metadata": {}, + "source": [ + "Note that here we closely follow reference\n", + "[Mean-Variance-VaR portfolios: MIQP formulation and performance analysis](https://arxiv.org/abs/2111.09773). One could read this reference for an overview on the topic." + ] + }, + { + "cell_type": "markdown", + "id": "98d58de7-4005-4836-9b30-55a6ce04df2f", + "metadata": {}, + "source": [ + "Consider n assets with the following portfolio:" + ] + }, + { + "cell_type": "markdown", + "id": "5bf58d94-2e32-4a34-9289-8be19473ec46", + "metadata": {}, + "source": [ + "$$x \\epsilon \\Delta = \\{ x \\epsilon \\mathbb{R}^{n} : \\sum_{k=1}^{n} x_{k}=1, x_{k} \\ge 0, k=1, \\dots, n \\}$$" + ] + }, + { + "cell_type": "markdown", + "id": "be7a6796-0b53-499d-8579-c710fc40975e", + "metadata": {}, + "source": [ + "with $x_{k}$ the percentage of the total portfolio invested in asset $k$ (let's call this $\\textit{Asset}_{k}$) and $n$ the total number of assets. The equality $\\sum_{k=1}^{n} x_{k}=1$ that 100% of the total portfolio is invested and $x_{k}\\ge 0$ indicates that all the percentages are positive (no-short sellings constraint).\n", + "\n", + "By having in mind that the investment decision at a particular point in time is made considering **T** equally likely scenarios, the portfolio return is given by:" + ] + }, + { + "cell_type": "markdown", + "id": "55deece6-9c98-45ff-9b73-1bceb783f2d0", + "metadata": {}, + "source": [ + "$$R_{Pt}(x)=\\sum_{k=1}^{n}x_{k}r_{kt}$$" + ] + }, + { + "cell_type": "markdown", + "id": "74a4485c-36d8-4257-a19b-e6b330d07a7b", + "metadata": {}, + "source": [ + "with the variables $r_{kt}$ corresponding to the return of each asset $k$ for the scenario $t \\epsilon \\{ 1, \\dots, T \\}$." + ] + }, + { + "cell_type": "markdown", + "id": "42f4e7c4-404c-4f06-bc29-448c3360127f", + "metadata": {}, + "source": [ + "The classical **Mean-Variance** portfolio optimization problem focuses on minimizing the variance (risk), while at the same time making sure that the expected return is above a specific value $\\eta$. It has the following convex form:" + ] + }, + { + "cell_type": "markdown", + "id": "81769ffb-ef50-4d4f-ba67-aea1d2a2a64d", + "metadata": {}, + "source": [ + "$$\\min \\sum_{k=1}^{n}\\sum_{j=1}^{n} x_{k}x_{j}\\sigma_{kj}$$" + ] + }, + { + "cell_type": "markdown", + "id": "7953dade-e77f-4ca0-a6b7-15e9d7704489", + "metadata": {}, + "source": [ + "$$\\text{s.t.}$$" + ] + }, + { + "cell_type": "markdown", + "id": "227a6a97-f5af-4b37-aec9-14c6abdb8297", + "metadata": {}, + "source": [ + "$$\\sum_{k=1}^{n} \\mu_{k}x_{k} \\ge \\eta$$ \n", + "\n", + "\n", + "$$\\sum_{k=1}^{n} x_{k}=1$$ \n", + "\n", + "\n", + "$$x_{k}\\ge 0 \\ \\text{for}\\ k=1,\\dots,n $$" + ] + }, + { + "cell_type": "markdown", + "id": "78d223bd-40f9-4191-821b-1a782b1b157e", + "metadata": {}, + "source": [ + "with $\\sigma^{2}_{P}(x)=\\sum_{k=1}^{n}\\sum_{j=1}^{n} x_{k}x_{j}\\sigma_{kj}$ the portfolio variance ($\\sigma_{kj}$ the covariance between the assets $k$ and $j$), $\\mu_{P}(x)=\\sum_{k=1}^{n} \\mu_{k}x_{k}$ the expected total return ($\\mu_{k}=\\frac{1}{T}\\sum_{t=1}^{T}r_{kt}$ is the expected return of asset k).\n", + "\\\n", + "\\\n", + "The inequality $\\sum_{k=1}^{n} \\mu_{k}x_{k} \\ge \\eta$ indicates that the expected total returns should be above or equal a specific target value ($\\eta$). \n", + "\\\n", + "\\\n", + "By solving the optimization problem above, one gets the **best distribution of assets**, or differently the optimal set of percentages $\\{x_{k}\\}$ of the total portfolio that should be invested in each one of the assets $k$. For example consider $\\textit{Asset}_1$, with the corresponding optimal percentage $x_{1}$. If the solution of the problem is $x_{1}=0.1$ that means that 10% of the total portfolio should be invested in $\\textit{Asset}_1$." + ] + }, + { + "cell_type": "markdown", + "id": "6843ae65-192a-4d62-aa96-79f615af7614", + "metadata": {}, + "source": [ + "The above optimization problem does not include the Value-at-Risk (VaR), which is an additional risk measure. $VaR_{\\epsilon}$ is defined as the **maximum loss** for scenarios $\\{1, \\dots, T\\}$ with $(1-\\epsilon)$ the given confidence level. $\\epsilon$ typically takes the values $\\epsilon=0.01, 0.05, 0.10$.\n", + "\n", + "To further understand what VaR is, first consider that for a given portfolio $x$, the portfolio loss is given by $L_{P}(x)=-\\sum_{k=1}^{n}x_{k}R_{k}$, with $R_{k}$ the return of asset $k$. $VaR_{\\epsilon}(x)$ is the value such that the portfolio loss $L_{P}(x)$ is above $VaR_{\\epsilon}(x)$ with probability $\\epsilon \\times 100 \\%$. If we include $VaR_{\\epsilon}$ in the **Mean-Variance** portfolio optimization problem we have the **Mean-Variance-VaR** approach. In this approach, a portfolio return $R_{P}(x)$ is preferred to $R_{P}(y)$ iff $\\mu_{P}(x)\\ge \\mu_{P}(y)$, $\\sigma^{2}_{P}(x)\\le \\sigma^{2}_{P}(y)$ and $VaR_{\\epsilon}(x)\\le VaR_{\\epsilon}(y)$." + ] + }, + { + "cell_type": "markdown", + "id": "eee858f6-43ec-4872-a014-21ef86e4ee0b", + "metadata": {}, + "source": [ + "By following [Mean-Variance-VaR portfolios: MIQP formulation and performance analysis](https://arxiv.org/abs/2111.09773) the **Mean-Variance-VaR** problem is written as a **Mixed-Integer Quadratic Programming (MIQP)** problem:" + ] + }, + { + "cell_type": "markdown", + "id": "cb3d5b16-9150-49af-84dc-5f89bcd08bf3", + "metadata": {}, + "source": [ + "$$min_{(x, r_{\\epsilon}, y)}\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}$$" + ] + }, + { + "cell_type": "markdown", + "id": "431b0e46-0516-46f6-9c52-258f0704697b", + "metadata": {}, + "source": [ + "$$\\text s.t.$$ \n", + "$$\\sum_{k=1}^{n}\\mu_{k}x_{k}\\ge \\eta$$\n", + "$$-r_{\\epsilon} \\le z$$\n", + "$$r_{\\epsilon}\\le \\sum_{k=1}^{n}r_{kt}x_{k}+M(1-y_{t})\\ \\text{for}\\ t=1, \\dots, T$$\n", + "$$\\sum_{t=1}^{T} y_{t} \\ge (1-\\epsilon)T$$ \n", + "$$\\sum_{k=1}^{n}x_{k}=1$$\n", + "$$x_{k} \\ge 0\\ \\text{for}\\ k=1, \\dots, n$$\n", + "$$y_{t}\\epsilon \\{ 0,1 \\} \\ \\text{for}\\ t=1, \\dots, T$$" + ] + }, + { + "cell_type": "markdown", + "id": "87424257-51ce-4280-ab5a-c5c12d8ef307", + "metadata": {}, + "source": [ + "with $VaR_{\\epsilon}(x)=-r_{\\epsilon}$, $r_{\\epsilon}$ a real and positive variable. Therefore $-r_{\\epsilon}$ represents the VaR of the portfolio and is bounded above by $z$ (which is real and positive, $z\\gt 0$), which is actually the target VaR. This is expressed as $-r_{\\epsilon} \\le z$ above.\n", + "\\\n", + "\\\n", + "$M$ is a large positive number that has to be fine-tuned in the optimization procedure. Find the optimal $M$ value here: [Mean-Variance-VaR portfolios: MIQP formulation and performance analysis](https://link.springer.com/article/10.1007/s00291-023-00719-x) and use it in the exercises below. $y_{t}$ (for $t=1,\\dots,T$) are boolean variables.\n", + "\\\n", + "\\\n", + "The inequalities $r_{\\epsilon}\\le \\sum_{k=1}^{n}r_{kt}x_{k}+M(1-y_{t})$ (one for each event $t$) indicate the following: if the **portfolio loss** $-\\sum_{k=1}^{n}r_{kt}x_{k}$ is above the VaR $-r_{\\epsilon}$ that means that $y_{t}$ must be 0 (for sufficiently big $M$). That practically means that if the portfolio loss is above the VaR, the event $t$ should **not** happen ($y_{t}=0$).\n", + "\\\n", + "\\\n", + "For the challenge, we simplify the problem as follows:\n", + "\n", + "$$ \\textbf{Mean-Variance-VaR Simplified Version}$$" + ] + }, + { + "cell_type": "markdown", + "id": "ef016e31-eaad-4c39-a47f-dbaa522d4d1e", + "metadata": {}, + "source": [ + "$$min_{(x, r_{\\epsilon}, y)}\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}-\\sum_{k=1}^{n}\\mu_{k}x_{k}$$" + ] + }, + { + "cell_type": "markdown", + "id": "408985e0-8c1d-4c12-9640-c117a68a0cc5", + "metadata": {}, + "source": [ + "$$\\text s.t.$$\n", + "$$-r_{\\epsilon} \\le z$$\n", + "$$r_{\\epsilon}\\le \\sum_{k=1}^{n}r_{kt}x_{k}+M(1-y_{t})\\ \\text{for}\\ t=1, \\dots, T$$\n", + "$$\\sum_{t=1}^{T} y_{t} \\ge (1-\\epsilon)T$$ \n", + "$$\\sum_{k=1}^{n}x_{k}=1$$\n", + "$$x_{k} \\ge 0\\ \\text{for}\\ k=1, \\dots, n$$\n", + "$$y_{t}\\epsilon \\{ 0,1 \\} \\ \\text{for}\\ t=1, \\dots, T$$" + ] + }, + { + "cell_type": "markdown", + "id": "6d1e1ae4-fb34-43fe-a9a7-7fcf9497efa6", + "metadata": {}, + "source": [ + "Specifically, we include the expected total returns, $\\sum_{k=1}^{n}\\mu_{k}x_{k}$, in the objective fuction $f(x)=\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}-\\sum_{k=1}^{n}\\mu_{k}x_{k}$ that is minimized. Now, by minimizing the objective function we select the **best distribution of assets** that maximize the return and minimize the variance (risk), while making sure that the equality/inequality constraints written above are also satisfied." + ] + }, + { + "cell_type": "markdown", + "id": "e8cc901b", + "metadata": {}, + "source": [ + "In the next sections you will learn how one can solve the **Mean-Variance-VaR Simplified Version** problem with quantum or quantum-inspired techniques.\n" + ] + }, + { + "cell_type": "markdown", + "id": "effe5813-0118-46ce-bd2a-560cb74e6a70", + "metadata": {}, + "source": [ + "
\n", + " \n", + "**STEPS:**\n", + " \n", + "1. Learn how to incorporate the equality/inequality constraints of the **Mean-Variance-VaR Simplified Version** problem in the objective function that is minimized.\n", + "2. Cast the problem into the QUBO formulation, by choosing an **encoding** for all the variables of step 1. The QUBO formulation can be used for finding the solution of the problem **classically** or with **quantum** or **quantum-inspired** methods.\n", + "3. Use Simulated Annealing to solve the problem. This is a specific algorithm used for **optimization problems**.\n", + "4. Evaluate the solutions of step 3.\n", + "5. Move to **quantum** optimization techniques such as Quantum Annealing or QAOA to solve the problem. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "c18ab12d-49b3-4a00-b12a-110c81522520", + "metadata": {}, + "source": [ + "### Installing required packages" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d76f8c15", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install -r requirements.txt" + ] + }, + { + "cell_type": "markdown", + "id": "19a0a45f", + "metadata": {}, + "source": [ + "### Reading in financial data\n", + "\n", + "\n", + "To examine the practical applicability of the mean-VaR model with quantum techniques, we will use a small dataset that compromises the weekly linear returns for Eurostoxx50 Market Index from 01-22-2007 to 05-06-2013 and contains up to 32 assets. You may find the associated file: *returns_data.txt*" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a78f8aea", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "# You may choose to select different parameters/values\n", + "number_assets = 3\n", + "T = 10\n", + "# Read returns\n", + "df = pd.read_csv('returns_data.txt', sep='\\s+')\n", + "\n", + "Rraw = df.values.T\n", + "\n", + "# Select the first N,T assets and scenarios, you may choose a different strategy if you would like to do so.\n", + "R = Rraw[:number_assets,:T]\n", + "\n", + "# Expected return of each asset\n", + "expected_returns = np.mean(R, axis = 1)\n", + "\n", + "# Covariance matrix of asset returns\n", + "covariance_matrix = np.cov(R)" + ] + }, + { + "cell_type": "markdown", + "id": "736c3eea-e219-4d6c-8457-3a4f21e9f6fc", + "metadata": {}, + "source": [ + "### Section 1: Incorporating equality/inequality constraints" + ] + }, + { + "cell_type": "markdown", + "id": "8a6ce336-2cfc-4a5a-80a4-6616b280adaf", + "metadata": {}, + "source": [ + "- Convert the inequalities of the **Mean-Variance-VaR Simplified Version** problem into equalities, with the use of slack variables and the penalty method approach. For reference one could read [A real world test of Portfolio Optimization with Quantum Annealing](https://arxiv.org/abs/2303.12601) (page 10).\n", + "Specifically, re-write the objective function above as a new objective function called L that includes the inequality constraints. To do that usually one introduces new variables, called **slack variables**, that transform an inequality constraint into an equality constraint. If you do that for each inequality of the optimization problem, what are the total number of variables to be optimized including the slack variables?\n", + "- In a similar way and by following the same reference, try to incorporate the one equality constraint, $\\sum_{k=1}^{n}x_{k}=1$ as a penalty term in the objective function L. Notice that now slack variables are not needed." + ] + }, + { + "cell_type": "markdown", + "id": "ec015dad-7449-433c-bd44-593e5fecb4ec", + "metadata": {}, + "source": [ + "
NOTE:\n", + "L has the following form: $L=\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}-\\sum_{k=1}^{n}\\mu_{k}x_{k}+\\textit{penalty terms}$, with the penalty terms to be found in this section (and include all the equalities and inequalities of the problem). This will need to be mapped to a quantum Hamiltonian in the following section. Each penalty term will correspond to one lagrange multiplier that will need to be fine-tuned in the next sections, so that the constraints are imposed.\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "23645c2f-0916-477e-9cf8-2ecb6ed114d1", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, + { + "cell_type": "markdown", + "id": "49892c5e-fee2-4c80-b115-3d474e815cdf", + "metadata": {}, + "source": [ + "$$L=\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}-\\sum_{k=1}^{n}\\mu_{k}x_{k}+\n", + "\\sum_{t=1}^{T}\\left( r_{\\epsilon} - \\left(\\sum_{k=1}^{n}r_{kt}x_{k}+M(1-y_{t})\\right) + s_{2,t} \\right)\n", + "+ \\left(\\sum_{t=1}^{T} y_{t} \\ge (1-\\epsilon)T - s_{3} \\right)\n", + "+ \\sum_{k=1}^{n} x_{k} - 1\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "id": "bb2982bd-fbb9-49de-8dbc-370e9390173b", + "metadata": {}, + "source": [ + "### Section 2: Encoding/Casting the problem into a QUBO formulation" + ] + }, + { + "cell_type": "markdown", + "id": "1282b39d-ec53-46b8-a149-b353c624c533", + "metadata": {}, + "source": [ + "Many discrete optimization problems that are NP hard can be mapped to quadratically unconstrained binary optimization (QUBO) problems. A QUBO can be expressed in the following form:" + ] + }, + { + "cell_type": "markdown", + "id": "557fd82b-e680-4819-8c41-d8381a5a3fe9", + "metadata": {}, + "source": [ + " $$\\text{min} \\quad z^{T}Qz$$" + ] + }, + { + "cell_type": "markdown", + "id": "4c50b9c4-bf08-4f63-8e9a-d9ad5e55e0d4", + "metadata": {}, + "source": [ + "with $z \\epsilon \\{ 0,1\\}^{N}$ the bit vector and $Q \\epsilon \\mathbb{R}^{N \\times N}$ the corresponding QUBO matrix. The aim of this exercise is to write the objective function L you found in **Section 1** in the QUBO form, with $z$ a vector that includes all the variables $\\{x_{i}\\}$ ($i \\in \\{1, \\dots n\\}$), $r_{\\epsilon}$, $\\{ y_{t} \\}$ ($t \\in \\{1, \\dots, T \\}$) and the slack variables introduced in **Section 1**." + ] + }, + { + "cell_type": "markdown", + "id": "f0f0847a-f9a6-4a03-9921-ea8b5bf0acb8", + "metadata": {}, + "source": [ + "Map the classical objective function of **Section 1** to a quantum Hamiltonian. Follow the steps:\n", + "- Map all the variables $\\{x_{i}\\}$, $r_{\\epsilon}$, $\\{ y_{t} \\}$ and the slack variables of **Section 1** into different binary variables. Reference [Approaching Collateral Optimization for NISQ and Quantum-Inspired Computing](https://arxiv.org/pdf/2305.16395.pdf) indicates how to map the slack variables into binary ones, with the use of the \"log-encoding\" in pages 4-5. However, reference [Solving the Optimal Trading Trajectory Problem Using a Quantum Annealer](https://arxiv.org/abs/1508.06182) presents different encodings.\n", + "\n", + "The encodings can be writen as a linear function of binary variables. For example, for the variable $x_{i}$ we have:\n", + "$$x_{i}=\\sum_{d=1}^{D}f(d)z_{di}$$\n", + "with $z_{di} \\epsilon \\{ 0,1\\}$ and $f(d)$ the function you are looking for (particular for each encoding). Notice that you will need to introduce $D$ new binary variables, for each variable $x_{i}$.\n", + "\n", + "- Which encoding did you use for each of the variables $\\{x_{i}\\}$, $r_{\\epsilon}$, $\\{y_{t}\\}$, which for the slack variables and why?\n", + "- As you can see, the total number of variables increase after the encoding. What is the total number of binary variables that you have after the mapping?\n", + "- One could cast the problem into a QUBO form, by finding $Q$. Then one can map it to a Hamiltonian by promoting all the binary variables (for example $z_{di}$) to binary operators ($z_{di} \\rightarrow \\hat{z}_{di}$). The Hamiltonian will then have the following form $\\hat{H}=\\hat{z}^{T}Q\\hat{z}$ with $Q \\epsilon \\mathbb{R}^{N \\times N}$ the corresponding QUBO matrix. You do **not** need to find the explicit QUBO form of the Hamiltonian $\\hat{H}$. Instead, substitute the encoding you found in this section to the Langrange formulation of **Section 1** (let's call it $L_{fin}$). Then, use $L_{fin}$ and with the help of [pyqubo](https://pyqubo.readthedocs.io/en/latest/getting_started.html#) find the QUBO formulation of the problem, by finding the matrix $Q$. One could then promote all the variables to operators, to find the quantum version of $L_{fin}$ (let's call it $\\hat{H}$). $L_{fin}$ and $\\hat{H}$ will be used in the following sections." + ] + }, + { + "cell_type": "markdown", + "id": "f1aefa04-e56e-4826-9be5-3eaf66ebb17e", + "metadata": {}, + "source": [ + "
NOTE 1:\n", + " \n", + "Notice that the above optimization problem can be translated to an Ising Hamiltonian with the following change of variables $x_{i}=\\frac{1-\\sigma_{i}}{2}$ as:\n", + " $$H(s)=-\\sum_{j}h_{j}\\sigma_{j}-\\sum_{j" + ] + }, + { + "cell_type": "markdown", + "id": "f7f83e50-386f-4a6b-a137-fd3cbbb82a47", + "metadata": {}, + "source": [ + "
NOTE 2 (Hint):\n", + " \n", + "Encoding requires finding the minimum and maximum values for each one of the variables of the problem. You will need to find them. \n", + "Notice that $-z \\le r_{\\epsilon} \\le 0$, with $z$ a positive, real number. Are the variables needed to be normalized and why?\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "9cabd342-4061-488b-9b3d-5d93d96344ec", + "metadata": {}, + "source": [ + "
NOTE 3 (Hint):\n", + "\n", + "Ignore how the choice of encoding might affect the noise level of a quantum device and only consider how it affects the granularity of the problem as well as the number of binary variables needed for the encoding of each variable of the problem. One could also read \n", + "[A real world test of Portfolio Optimization with Quantum Annealing](https://arxiv.org/abs/2303.12601). \n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "897a8e15-2da5-4ae2-9108-31aa005d6057", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "553d8b31", + "metadata": {}, + "outputs": [], + "source": [ + "# write your code here" + ] + }, + { + "cell_type": "markdown", + "id": "ed9d5b11-b2f3-4c79-bdf9-000cd7685f85", + "metadata": {}, + "source": [ + "
\n", + " \n", + "BONUS EXERCISE: \n", + "As you notice the number of binary operators one has to use scales with the number of variables. Introducing the slack variables is therefore very costly. Try to suggest a new way of implementing the inequalities, without a lot of details. You can use the help of reference [Unbalanced penalization: A new approach to encode inequality constraints of combinatorial problems for quantum optimization algorithms](https://arxiv.org/abs/2211.13914).\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "51466cca-e371-4f55-bdee-7b2eea6159d8", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, + { + "cell_type": "markdown", + "id": "9344d008-0e1a-45fd-9aa3-1399e56b859c", + "metadata": {}, + "source": [ + "### Section 3: Simulated Annealing" + ] + }, + { + "cell_type": "markdown", + "id": "1a9abb2c-9062-451e-9b4b-8009bd455e3c", + "metadata": {}, + "source": [ + "Optimization problems, like the one above, can be solved with the use of simulated annealing. It is one of the most preferred heuristic methods to solve optimization problems, since it avoids local minima." + ] + }, + { + "cell_type": "markdown", + "id": "49533860-07ce-4bea-a2b8-c1a8cd3d2670", + "metadata": {}, + "source": [ + "- Using simulated annealing and the **data** calculate the ground state and find the best solution of the QUBO problem, $L_{fin}$, found in **Section 2**. Note that the lagrange multipliers in front of the penalty terms/constraints will need to be fine-tuned so that the equalities/inequalities of the problem are all satisfied. The output of the algorithm will give you the optimal values of the binary variables of the encoding of $\\{x_{i}\\}$, $r_{\\epsilon}$, $\\{y_{t}\\}$ and the slack variables so that the return is maximized, the risk is minimized while at the same time the inequality/equality constraints of the problem are all satisfied. In the next section you will learn how to evaluate your solutions." + ] + }, + { + "cell_type": "markdown", + "id": "9a897de7-1efd-414e-bf16-a3f2353c9f6b", + "metadata": {}, + "source": [ + "
NOTE 1 (Hint):\n", + " \n", + "\n", + "Feel free to first read any references provided online for Simulated Annealing like [Optimization Simulated Annealing](https://www.science.org/doi/10.1126/science.220.4598.671). You do not need to write your own code for this Section. Instead try [pyqubo](https://pyqubo.readthedocs.io/en/latest/getting_started.html#) and [D-Wave neal](https://docs.ocean.dwavesys.com/projects/neal/en/latest/).\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "54c2a1b7-feda-4461-bd63-b5e183e0b8f7", + "metadata": {}, + "source": [ + "
NOTE 2 (Hint):\n", + "\n", + " [pyqubo](https://pyqubo.readthedocs.io/en/latest/getting_started.html#) offers an easy way to evaluate whether the constraints are satisfied or not. Use it so that you are able to fine-tune the lagrange multipliers and get your solution to be as close as possible in satisfying the constraints. \n", + " \n", + " The lagrange multipliers act as relative weights between the different terms of the QUBO problem. Fine-tuning them so that the constraints of the problem are satisfied is **not** trivial. The fine-tuning process goes as following:\n", + " \n", + " Consider the following constraint optimization problem:\n", + " $$\\text{min} f(\\textbf{x})$$\n", + " subject to the constraint:\n", + " $$c(\\textbf{x})=0.$$\n", + "We can find a solution to this problem with the use of the **penalty method** approach, where we define a new objective function that includes the constraint as an added penalty term in the objective fuction. The $k^{th}$ step of the now unconstraint optimization problem is the following:\n", + "$$\\text{min}\\Psi_{k}(\\textbf{x})=f(\\textbf{x})+\\mu_{k}c(\\textbf{x})^{2}$$\n", + " with $\\mu_{k}$ the lagrange multiplier of this step (or else the penalty term coefficient). In order to fine-tune the langrange multiplier you start with a large-enough value of $\\mu_{1}$ (in comparison to the coefficients of the non-penalty terms of the QUBO problem). In the next steps of the iteration you increase the value of the coefficient until the constraints are satisfied.\n", + " \n", + " Specifically take a look at [pyqubo--validation of the constraints](https://pyqubo.readthedocs.io/en/latest/getting_started.html#validation-of-constraints). One could check whether the constraints are satisfied by making sure the energy contribution of each penalty term is 0. [pyqubo--validation of the constraints](https://pyqubo.readthedocs.io/en/latest/getting_started.html#validation-of-constraints) outputs the energy contribution of each penalty term. If you do not manage to get the energy contribution of the penalty terms to exactly 0, make sure they are as close as possible to that. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "ce724e8f-cc21-49fb-89b6-7e2b1e93296f", + "metadata": {}, + "source": [ + "
NOTE 3 (Hint):\n", + "The binary variables used for the encoding of $\\{x_{i}\\}$, $r_{\\epsilon}$, $\\{y_{t}\\}$ and all the slack variables affect the granularity of the problem. Choose the number of binary variables you use for the encoding of each one of the variables $\\{x_{i}\\}$, $r_{\\epsilon}$ and the slack variables. Why do you think that's a reasonable number of binary variables? How many binary variables do you need to use for the variables $\\{y_{t}\\}$?\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a359a291-bbb0-4f4f-97fd-acd5f90d8eb6", + "metadata": {}, + "outputs": [], + "source": [ + "# write your code here" + ] + }, + { + "cell_type": "markdown", + "id": "5e4786ea-1db6-46a6-b9f8-d1bfcdb88b20", + "metadata": {}, + "source": [ + "### Section 4: Simulated Annealing--Verifying your solutions" + ] + }, + { + "cell_type": "markdown", + "id": "37e4d030-3484-4fe2-b2de-7c2d374e58af", + "metadata": {}, + "source": [ + "In the previous section you solved the **Mean-Variance-VaR** problem with Simulated Annealing, making sure that the penalty terms are imposed properly, so that the equalities/inequalities of the problem are satisfied. In this section, you will further test your solutions.\n", + "- From the output of **Section 3** you get the optimal values of the binary variables of the encoding. For example, for the variable $x_{i}$ we have:\n", + "$$x_{i}=\\sum_{d=1}^{D}f(d)z_{di}$$\n", + "with $\\{ z_{di} \\}$ the output of **Section 3** and $f(d)$ the function you have chosen for the encoding. Use this output in order to calculate the optimal percentages of the total portfolio invested in each one of the assets, $\\{x_{i}\\}$.\n", + "- After obtaining $\\{ x_{i} \\}$ use them to calculate the **expected total returns**: $$\\mu_{P}(x):=\\sum_{k=1}^{n}\\mu_{k}x_{k}$$\n", + " and **variance**: $$V(x):=\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}$$\n", + "- In a similar way, from the output of **Section 3** calculate the $VaR_{\\epsilon}=-r_{\\epsilon}$.\n", + "- Run the code of **Section 3** multiple times. Each time calculate the expected returns, the variance and $VaR_{\\epsilon}$. Peak the best result and justify your answer.\n", + "- Calculate the historical VaR with the use of the following function:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "95761549", + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_historical_VaR(weights, mu_R, confidence_level=0.95):\n", + " \n", + " portfolio_returns = np.dot(mu_R, np.transpose(np.array(weights)))\n", + "\n", + " VaR = np.percentile(portfolio_returns, 100 * (1 - confidence_level))\n", + " \n", + " return -VaR" + ] + }, + { + "cell_type": "markdown", + "id": "09d0c42b", + "metadata": {}, + "source": [ + "with $\\textit{weights}$ being a list that includes the optimal values (your solution) for the variables $\\{x_{i}\\}$ and $\\textit{mu_R}$ the expected returns of the assets (given by the data). Compare the return value got from this function to $VaR_{\\epsilon}$ calculated above." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c6d5972", + "metadata": {}, + "outputs": [], + "source": [ + "# write your code here" + ] + }, + { + "cell_type": "markdown", + "id": "e32da760-2d7c-44cc-b541-0fd576eaedf2", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, + { + "cell_type": "markdown", + "id": "9acc19d6-5b85-4ef4-aef4-7cdfe709b566", + "metadata": {}, + "source": [ + "### Section 5: Quantum optimization (Quantum Annealing and/or QAOA)" + ] + }, + { + "cell_type": "markdown", + "id": "ac6a4eab-e29a-470d-ba29-a3995c8eac10", + "metadata": {}, + "source": [ + "\n", + "**Note**: For the exercises below use the $\\hat{H}$ you found in **Section 2**, with the same encoding you used in that exercise and with the use of the **data** provided in the beginning of the challenge.\n", + "\n", + "**STEP 1:** Study the **Mean-Variance-VaR Simplified Version** problem with QAOA and Quantum Annealing. \n", + "\n", + "The Quantum Approximate Optimization Algorithm (QAOA) was first introduced in [A Quantum Approximate Optimization Algorithm](https://arxiv.org/abs/1411.4028). QAOA is a popular method to solve combinatorial optimization problems in noisy intermediate-scale quantum (NISQ) devices.\n", + "\n", + "Useful tutorials on implementing QAOA can be found here: \n", + "- [Pulser tutorial QAOA](https://pulser.readthedocs.io/en/latest/tutorials/qubo.html)\n", + "- [Qiskit QAOA](https://docs.quantum.ibm.com/api/qiskit/qiskit.algorithms.minimum_eigensolvers.QAOA), [Qiskit tutorial QAOA](https://qiskit.org/documentation/stable/0.40/tutorials/algorithms/05_qaoa.html)\n", + "- [pyQAOA tutorial QAOA](https://grove-docs.readthedocs.io/en/latest/qaoa.html)\n", + "- [PennyLane tutorial QAOA](https://pennylane.ai/qml/demos/tutorial_qaoa_intro/)\n", + "- [OpenQAOA-EntropicaLabs](https://openqaoa.entropicalabs.com/)\n", + "\n", + "For Quantum Annealing, you may read this reference [D-Wave, Quantum Annealing](https://docs.dwavesys.com/docs/latest/c_gs_2.html#getting-started-qa) and follow [D-Wave Ocean Software documentation](https://docs.ocean.dwavesys.com/en/stable/index.html) for the implementation. \n", + "In [Solving the Optimal Trading Trajectory Problem Using a Quantum Annealer](https://arxiv.org/abs/1508.06182), the authors explain how the choice of encoding might differ when considering solving an optimization problem with quantum annealing instead of simulated annealing.\n", + " \n", + "Do not implement anything at the moment. This step is for introducing you to different quantum or quantum-inspired algorithms one could utilize for this problem.\n", + "\n", + "**STEP 2:** In **Section 3** you used [D-Wave neal](https://docs.ocean.dwavesys.com/projects/neal/en/latest/) to solve the problem with Simulated Annealing. As also seen in the previous step, [D-Wave Ocean](https://docs.ocean.dwavesys.com/en/stable/getting_started.html) gives you immediate, secure access to D-Wave quantum and hybrid solvers. Study the capabilities of [D-Wave Ocean](https://docs.ocean.dwavesys.com/en/stable/getting_started.html) and answer the following questions:\n", + "\n", + "- For reasonable granularity (i.e. number of qubits per encoded variable) how many assets $n$ and events $T$ you can study with a quantum device and D-Wave? For that you will need to find the total number of qubits that you can explore with [D-Wave Ocean](https://docs.ocean.dwavesys.com/en/stable/getting_started.html) for the algorithm of your choice. Notice that the resources available to the public are much less than the capabilities of these devices.\n", + "\n", + "**STEP 3:** After exploring the capabilities of [D-Wave Ocean Software documentation](https://docs.ocean.dwavesys.com/en/stable/index.html), you are encouraged to use a **quantum simulator/backend** to study the **Mean-Variance-VaR Simplified Version** problem with the **data** provided in the beginning of the challenge (feel free to change $T$ and $n$ if needed) and any method of your choice. For this, you can use your qBraid account. Explore the options below:\n", + "\n", + "- [Qiskit](https://docs.quantum.ibm.com/api/qiskit)\n", + "- [Amazon Braket](https://docs.aws.amazon.com/braket/latest/developerguide/what-is-braket.html)\n", + "\n", + "Or even more, you may also opt to explore the usage of GPUs for simulating quantum algorithms. For example, see a recent [work](https://www.jpmorgan.com/technology/technology-blog/quantum-optimization-research) that studies QAOA scaling performance on a fast GPU-specific QAOA simulator.\n", + "\n", + "No matter what algorithm you choose, **you are encouraged to run small-scale simulations of the problems on quantum backends and simulators, always keeping in mind the resources that you are utilizing and their cost**. What problems/limitations do you encounter in comparison with simulated annealing?" + ] + }, + { + "cell_type": "markdown", + "id": "dbc17d65-627d-4805-ac9f-3a3803bfc70d", + "metadata": {}, + "source": [ + "
Note 1 (Hint):\n", + " \n", + " One could read the following references: \n", + " \n", + "- [Quantum Optimization: Potential, Challenges, and the Path Forward](https://arxiv.org/abs/2312.02279) and references within.\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "8b4a5f08-14de-4d26-8031-8c1b2cd4f003", + "metadata": {}, + "source": [ + "
Note 2 (Hint):\n", + " \n", + "One can take a look at the [IBM Quantum Development Roadmap to 2033](https://newsroom.ibm.com/2023-12-04-IBM-Debuts-Next-Generation-Quantum-Processor-IBM-Quantum-System-Two,-Extends-Roadmap-to-Advance-Era-of-Quantum-Utility) and [QuEra's Quantum Computing Roadmap](https://www.quera.com/press-releases/quera-computing-releases-a-groundbreaking-roadmap-for-advanced-error-corrected-quantum-computers-pioneering-the-next-frontier-in-quantum-innovation) for an idea about the current and predicted quantum capabilities.\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "990a82c7-6ccc-4552-8b86-97a95fece3cd", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa60be68", + "metadata": {}, + "outputs": [], + "source": [ + "# write your code here" + ] + }, + { + "cell_type": "markdown", + "id": "95e10967", + "metadata": {}, + "source": [ + "### Section 6 (BONUS):\n", + "\n", + "Above you followed specific steps and used simulated annealing as well as quantum or quantum-inspired methods to solve the problem of interest. To do this, you were instructed to incorporate the constraints of the problem (equalities/inequalities) in the objective function and then to find the QUBO formulation of the problem in question. In this exercise you are asked to think of another way to solve the **Mean-Variance-VaR Simplified Version** problem with quantum, quantum-inspired or hybrid methods, without following any of the steps mentioned in this challenge." + ] + }, + { + "cell_type": "markdown", + "id": "d57153d6", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "067cea0c", + "metadata": {}, + "outputs": [], + "source": [ + "# write your code here" + ] + }, + { + "cell_type": "markdown", + "id": "71ae8d5b-93a8-4305-95a1-0cebf1f29cf6", + "metadata": {}, + "source": [ + "### Section 7: Pitch your quantum strategy to a client" + ] + }, + { + "cell_type": "markdown", + "id": "ecb9a766-b6df-4b91-b0ff-13ced8fc5b52", + "metadata": {}, + "source": [ + "Imagine that you are part of the Quantum team at Moody's. You are meeting the board of stakeholders of an important company in the US. Given what you now know about the current quantum hardware capabilities, in which quantum algorithms should the stakeholders invest and why? Prepare your pitch focusing only on portfolio optimization problems. How do you think quantum could potentially avoid the drawbacks of classical optimization algorithms and why should a company invest in quantum today?" + ] + }, + { + "cell_type": "markdown", + "id": "a440d8cd-2ed2-45e9-8a89-895847db823c", + "metadata": {}, + "source": [ + "
Hint:\n", + " \n", + " One could read the following references: \n", + " \n", + "- [Quantum Optimization: Potential, Challenges, and the Path Forward](https://arxiv.org/abs/2312.02279) \n", + "- [QAOA with N⋅p≥200](https://arxiv.org/abs/2303.02064) \n", + "- [Evidence of Scaling Advantage for the Quantum Approximate Optimization Algorithm on a Classically Intractable Problem](https://arxiv.org/pdf/2308.02342.pdf)\n", + "- [Towards optimization under uncertainty for fundamental models in energy markets using quantum computers](https://arxiv.org/abs/2301.01108)\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "550f2bc1-7726-417e-88b5-8253ac12baeb", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, + { + "cell_type": "markdown", + "id": "c098599c-7ab0-48b1-9e33-51d22502310d", + "metadata": {}, + "source": [ + "# This is the end of the challenge. Good luck!" + ] + } + ], + "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.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index 2f33633..d0cc91e 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -311,13 +311,23 @@ "
" ] }, + { + "cell_type": "markdown", + "id": "c18ab12d-49b3-4a00-b12a-110c81522520", + "metadata": {}, + "source": [ + "### Installing required packages" + ] + }, { "cell_type": "code", "execution_count": null, "id": "d76f8c15", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "#!pip install -r requirements.txt" + ] }, { "cell_type": "markdown", @@ -332,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 6, "id": "a78f8aea", "metadata": {}, "outputs": [], @@ -344,7 +354,7 @@ "number_assets = 3\n", "T = 10\n", "# Read returns\n", - "df = pd.read_csv('returns_data.txt',delim_whitespace=True)\n", + "df = pd.read_csv('returns_data.txt', sep='\\s+')\n", "\n", "Rraw = df.values.T\n", "\n", @@ -394,6 +404,18 @@ "**Answer:**" ] }, + { + "cell_type": "markdown", + "id": "49892c5e-fee2-4c80-b115-3d474e815cdf", + "metadata": {}, + "source": [ + "$$L=\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}-\\sum_{k=1}^{n}\\mu_{k}x_{k}+\n", + "\\sum_{t=1}^{T}\\left( r_{\\epsilon} - \\left(\\sum_{k=1}^{n}r_{kt}x_{k}+M(1-y_{t})\\right) + s_{2,t} \\right)\n", + "+ \\left(\\sum_{t=1}^{T} y_{t} \\ge (1-\\epsilon)T - s_{3} \\right)\n", + "+ \\sum_{k=1}^{n} x_{k} - 1\n", + "$$" + ] + }, { "cell_type": "markdown", "id": "bb2982bd-fbb9-49de-8dbc-370e9390173b", diff --git a/requirements.txt b/requirements.txt index be9f9d2..11b09bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,5 @@ dimod dwave-neal scipy matplotlib +notebook +pyarrow From bcf2ae1522b35c7d0dfea8ef5c9381d0827de1b3 Mon Sep 17 00:00:00 2001 From: Lizard Empress Date: Sat, 3 Feb 2024 17:16:07 -0500 Subject: [PATCH 03/12] equations and rationale for part 2 --- moodys_challenge.ipynb | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index d0cc91e..b3927ab 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -411,7 +411,7 @@ "source": [ "$$L=\\sum_{k=1}^{n}\\sum_{j=1}^{n}x_{k}x_{j}\\sigma_{kj}-\\sum_{k=1}^{n}\\mu_{k}x_{k}+\n", "\\sum_{t=1}^{T}\\left( r_{\\epsilon} - \\left(\\sum_{k=1}^{n}r_{kt}x_{k}+M(1-y_{t})\\right) + s_{2,t} \\right)\n", - "+ \\left(\\sum_{t=1}^{T} y_{t} \\ge (1-\\epsilon)T - s_{3} \\right)\n", + "+ \\left(\\sum_{t=1}^{T} y_{t} - (1-\\epsilon)T - s_{3} \\right)\n", "+ \\sum_{k=1}^{n} x_{k} - 1\n", "$$" ] @@ -503,6 +503,39 @@ "" ] }, + { + "cell_type": "markdown", + "id": "a0f4be8f", + "metadata": {}, + "source": [ + "$\n", + "x_i = \\sum_{d = 1}^{D} (\\frac{1}{2^{D-1}})2^{d-1} z_{d_i}\n", + "$ this is $n \\times D$\n", + "\n", + "We've encoded the $x_i$ as binary since they are floating point numbers.\n", + "\n", + "
\n", + "\n", + "$\n", + "y_t \\in \\{0,1\\}\n", + "$ from the problem formulation, there are $T$ of them. \n", + "\n", + "
\n", + "\n", + "$r_{\\epsilon} = -z + (Z + z) r_{\\epsilon}'$ \n", + "\n", + "where $-z$ is the minimum for $r_{\\epsilon}$. \n", + "\n", + "And $r_{\\epsilon}' = \\sum_{d = 1}^{D} \\frac{1}{2^{D-1}}2^{d-1} z_{di} $ is the normalized version, there are $D$ of them \n", + "\n", + "
\n", + "\n", + "$S = \\sum_{d = 1}^{D}2^{d-1}S_d$ and there are $(T+1) D$ of these\n", + "\n", + "\n", + "So total number of variables is $D(n + T + 2) + T$\n" + ] + }, { "cell_type": "markdown", "id": "897a8e15-2da5-4ae2-9108-31aa005d6057", From ce148e82bfa1c4c46d55020806cb03ad157676b3 Mon Sep 17 00:00:00 2001 From: Lakshika Rathi Date: Sat, 3 Feb 2024 18:20:54 -0500 Subject: [PATCH 04/12] ex2 --- moodys_challenge.ipynb | 262 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 257 insertions(+), 5 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index 2f33633..dbaa1b3 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -332,7 +332,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 63, "id": "a78f8aea", "metadata": {}, "outputs": [], @@ -341,7 +341,7 @@ "import pandas as pd\n", "\n", "# You may choose to select different parameters/values\n", - "number_assets = 3\n", + "number_assets = 2\n", "T = 10\n", "# Read returns\n", "df = pd.read_csv('returns_data.txt',delim_whitespace=True)\n", @@ -489,9 +489,21 @@ "**Answer:**" ] }, + { + "cell_type": "markdown", + "id": "4cb86004", + "metadata": {}, + "source": [ + "We use the binary encoding for $\\{x_{i}\\}$, which is written as $\\{x_{i}\\}$ = \\[sum_\\]\n", + "\n", + "- Which encoding did you use for each of the variables $\\{x_{i}\\}$, $r_{\\epsilon}$, $\\{y_{t}\\}$, which for the slack variables and why?\n", + "- As you can see, the total number of variables increase after the encoding. What is the total number of binary variables that you have after the mapping?\n", + "- One could cast the problem into a QUBO form, by finding $Q$. Then one can map it to a Hamiltonian by promoting all the binary variables (for example $z_{di}$) to binary operators ($z_{di} \\rightarrow \\hat{z}_{di}$). The Hamiltonian will then have the following form $\\hat{H}=\\hat{z}^{T}Q\\hat{z}$ with $Q \\epsilon \\mathbb{R}^{N \\times N}$ the corresponding QUBO matrix. You do **not** need to find the explicit QUBO form of the Hamiltonian $\\hat{H}$. Instead, substitute the encoding you found in this section to the Langrange formulation of **Section 1** (let's call it $L_{fin}$). Then, use $L_{fin}$ and with the help of [pyqubo](https://pyqubo.readthedocs.io/en/latest/getting_started.html#) find the QUBO formulation of the problem, by finding the matrix $Q$. One could then promote all the variables to operators, to find the quantum version of $L_{fin}$ (let's call it $\\hat{H}$). $L_{fin}$ and $\\hat{H}$ will be used in the following sections." + ] + }, { "cell_type": "code", - "execution_count": null, + "execution_count": 64, "id": "553d8b31", "metadata": {}, "outputs": [], @@ -499,6 +511,241 @@ "# write your code here" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "46350de7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 65, + "id": "20b2251c", + "metadata": {}, + "outputs": [], + "source": [ + "from pyqubo import Array\n", + "\n", + "D = 5\n", + "\n", + "x = Array.create('x', shape=(number_assets, D), vartype=\"BINARY\")\n", + "y = Array.create('y', shape=T, vartype=\"BINARY\")\n", + "s = Array.create('s', shape=(T+1, D), vartype=\"BINARY\")\n", + "r_e = Array.create('r_e', shape=D, vartype=\"BINARY\")" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "d84cacd7", + "metadata": {}, + "outputs": [], + "source": [ + "def binary_encode(x, D):\n", + " bin_x = 0\n", + " for d in range(D):\n", + " bin_x += (1/2**(D-1))*(2**d)*x[d]\n", + " return bin_x\n", + "\n", + "def encode_s(s, D):\n", + " bin_s = 0\n", + " for d in range(D):\n", + " bin_s += (2**d)*s[d]\n", + " return bin_s\n", + "\n", + "def encode_r_e(r_e, z, Z):\n", + " bin_r = 0\n", + " for d in range(D):\n", + " bin_r += (1/2**(D-1))*(2**d)*r_e[d]\n", + " return -z+(Z+z)*bin_r" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "id": "a1b3470c", + "metadata": {}, + "outputs": [], + "source": [ + "def H1(covariance_matrix, x):\n", + " ham_1 = 0\n", + " n, D = x.shape\n", + " for i in range(n):\n", + " x_i = binary_encode(x[i], D)\n", + " for j in range(n):\n", + " x_j = binary_encode(x[j], D)\n", + " ham_1 += covariance_matrix[i, j]*x_i*x_j\n", + " return ham_1" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "b05c7c20", + "metadata": {}, + "outputs": [], + "source": [ + "def H2(expected_returns, x):\n", + " ham_2 = 0\n", + " n, D = x.shape\n", + " for i in range(n):\n", + " ham_2 -= expected_returns[i]*binary_encode(x[i], D)\n", + " return ham_2" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "fe40d5ff", + "metadata": {}, + "outputs": [], + "source": [ + "def H3_t(r_e, x, R, M, y, s, z, Z, t):\n", + " ham_3 = encode_r_e(r_e, z, Z)\n", + " n, D = x.shape\n", + " for i in range(n):\n", + " ham_3 -= R[i, t]*binary_encode(x[i], D)\n", + " ham_3 += M*(1-y[t])\n", + " ham_3 += encode_s(s[t], D)\n", + " return ham_3\n", + "\n", + "def H3(r_e, x, R, M, y, s, z, Z):\n", + " ham_3 = 0\n", + " for t in range(T):\n", + " ham_3 += (H3_t(r_e, x, R, M, y, s, z, Z, t))**2\n", + " return ham_3" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "e72ceb1b", + "metadata": {}, + "outputs": [], + "source": [ + "def H4(y, T, s, epsilon, D):\n", + " ham_4 = 0\n", + " for t in range(T):\n", + " ham_4 += y[t]\n", + " ham_4 -= (1-epsilon)*T\n", + " ham_4 -= encode_s(s[-1], D)\n", + " return ham_4**2" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "id": "ff85af2f", + "metadata": {}, + "outputs": [], + "source": [ + "def H5(x):\n", + " ham_5 = 0\n", + " n, D = x.shape\n", + " for i in range(n):\n", + " ham_5 += binary_encode(x[i], D)\n", + " return (ham_5-1)**2" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "ba96d396", + "metadata": {}, + "outputs": [], + "source": [ + "lambda_ = [1, 1, 1, 1, 1]\n", + "M = 10\n", + "z = 0.2\n", + "Z = 10\n", + "epsilon = 0.05\n", + "H = lambda_[0]*H1(covariance_matrix, x)+lambda_[1]*H2(expected_returns, x)+lambda_[2]*H3(r_e, x, R, M, y, s, z, Z)+lambda_[3]*H4(y, T, s, epsilon, D)+lambda_[4]*H5(x)" + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "id": "183ed083", + "metadata": {}, + "outputs": [], + "source": [ + "model = H.compile()" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "613b780f", + "metadata": {}, + "outputs": [], + "source": [ + "qubo, offset = model.to_qubo()" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "71ebf9a7", + "metadata": {}, + "outputs": [], + "source": [ + "bqm = model.to_bqm()" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "cb18428e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'y[9]': 1, 'y[8]': 1, 'y[7]': 1, 'y[0]': 1, 'x[1][2]': 1, 'y[6]': 1, 'x[1][1]': 1, 'x[0][2]': 0, 'x[0][1]': 0, 'x[0][0]': 1, 's[9][4]': 0, 's[9][1]': 0, 's[9][0]': 0, 's[8][3]': 0, 's[8][2]': 0, 's[8][1]': 0, 's[8][0]': 0, 's[7][4]': 0, 's[9][3]': 0, 's[7][3]': 0, 'y[4]': 1, 's[5][1]': 0, 's[6][4]': 0, 's[0][2]': 0, 's[6][0]': 0, 's[0][0]': 0, 's[5][4]': 0, 'x[0][4]': 0, 's[2][3]': 0, 's[5][0]': 0, 'y[3]': 1, 's[4][4]': 0, 'y[2]': 1, 's[8][4]': 0, 's[6][1]': 0, 's[9][2]': 0, 's[4][3]': 0, 'r_e[1]': 0, 's[4][2]': 0, 's[3][4]': 0, 's[3][1]': 0, 'x[0][3]': 0, 's[7][2]': 0, 's[10][0]': 0, 's[4][1]': 0, 'y[5]': 1, 's[3][0]': 0, 's[6][3]': 0, 'r_e[0]': 0, 's[2][4]': 0, 's[7][1]': 0, 's[2][1]': 0, 's[10][2]': 0, 's[1][2]': 0, 's[2][2]': 0, 's[7][0]': 0, 's[6][2]': 0, 's[1][1]': 0, 'r_e[3]': 0, 's[0][4]': 0, 's[1][0]': 0, 's[1][3]': 0, 's[4][0]': 0, 'y[1]': 1, 's[3][2]': 0, 's[10][4]': 0, 's[1][4]': 0, 'x[1][3]': 1, 's[5][3]': 0, 's[3][3]': 0, 'x[1][4]': 0, 'x[1][0]': 1, 's[10][1]': 0, 's[0][3]': 0, 's[2][0]': 0, 's[10][3]': 0, 's[0][1]': 0, 'r_e[2]': 0, 's[5][2]': 0, 'r_e[4]': 0}\n" + ] + } + ], + "source": [ + "import neal\n", + "sa = neal.SimulatedAnnealingSampler()\n", + "sampleset = sa.sample(bqm, num_reads=10)\n", + "decoded_samples = model.decode_sampleset(sampleset)\n", + "best_sample = min(decoded_samples, key=lambda x: x.energy)\n", + "print(best_sample.sample)" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "daa98042", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "80" + ] + }, + "execution_count": 77, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(T+number_assets+2)*D+T" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92ce9096", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "ed9d5b11-b2f3-4c79-bdf9-000cd7685f85", @@ -835,7 +1082,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "Python 3.9.6 64-bit", "language": "python", "name": "python3" }, @@ -849,7 +1096,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.5" + "version": "3.9.6" + }, + "vscode": { + "interpreter": { + "hash": "20bf69066c0dd38d51965b69d5e1b6e387082e3198ba56e97997ac55f4e50ad0" + } } }, "nbformat": 4, From ddb1cc09e9878a8c30dd931ab31d427c0547c1ab Mon Sep 17 00:00:00 2001 From: Lakshika Rathi Date: Sat, 3 Feb 2024 21:07:36 -0500 Subject: [PATCH 05/12] ex4 --- moodys_challenge.ipynb | 262 ++++++++++++++++++++++++++++------------- 1 file changed, 181 insertions(+), 81 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index dbaa1b3..e6a9e6f 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -341,7 +341,7 @@ "import pandas as pd\n", "\n", "# You may choose to select different parameters/values\n", - "number_assets = 2\n", + "number_assets = 3\n", "T = 10\n", "# Read returns\n", "df = pd.read_csv('returns_data.txt',delim_whitespace=True)\n", @@ -554,6 +554,7 @@ " for d in range(D):\n", " bin_s += (2**d)*s[d]\n", " return bin_s\n", + " #return LogEncInteger(s)\n", "\n", "def encode_r_e(r_e, z, Z):\n", " bin_r = 0\n", @@ -664,80 +665,6 @@ "H = lambda_[0]*H1(covariance_matrix, x)+lambda_[1]*H2(expected_returns, x)+lambda_[2]*H3(r_e, x, R, M, y, s, z, Z)+lambda_[3]*H4(y, T, s, epsilon, D)+lambda_[4]*H5(x)" ] }, - { - "cell_type": "code", - "execution_count": 73, - "id": "183ed083", - "metadata": {}, - "outputs": [], - "source": [ - "model = H.compile()" - ] - }, - { - "cell_type": "code", - "execution_count": 74, - "id": "613b780f", - "metadata": {}, - "outputs": [], - "source": [ - "qubo, offset = model.to_qubo()" - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "id": "71ebf9a7", - "metadata": {}, - "outputs": [], - "source": [ - "bqm = model.to_bqm()" - ] - }, - { - "cell_type": "code", - "execution_count": 82, - "id": "cb18428e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'y[9]': 1, 'y[8]': 1, 'y[7]': 1, 'y[0]': 1, 'x[1][2]': 1, 'y[6]': 1, 'x[1][1]': 1, 'x[0][2]': 0, 'x[0][1]': 0, 'x[0][0]': 1, 's[9][4]': 0, 's[9][1]': 0, 's[9][0]': 0, 's[8][3]': 0, 's[8][2]': 0, 's[8][1]': 0, 's[8][0]': 0, 's[7][4]': 0, 's[9][3]': 0, 's[7][3]': 0, 'y[4]': 1, 's[5][1]': 0, 's[6][4]': 0, 's[0][2]': 0, 's[6][0]': 0, 's[0][0]': 0, 's[5][4]': 0, 'x[0][4]': 0, 's[2][3]': 0, 's[5][0]': 0, 'y[3]': 1, 's[4][4]': 0, 'y[2]': 1, 's[8][4]': 0, 's[6][1]': 0, 's[9][2]': 0, 's[4][3]': 0, 'r_e[1]': 0, 's[4][2]': 0, 's[3][4]': 0, 's[3][1]': 0, 'x[0][3]': 0, 's[7][2]': 0, 's[10][0]': 0, 's[4][1]': 0, 'y[5]': 1, 's[3][0]': 0, 's[6][3]': 0, 'r_e[0]': 0, 's[2][4]': 0, 's[7][1]': 0, 's[2][1]': 0, 's[10][2]': 0, 's[1][2]': 0, 's[2][2]': 0, 's[7][0]': 0, 's[6][2]': 0, 's[1][1]': 0, 'r_e[3]': 0, 's[0][4]': 0, 's[1][0]': 0, 's[1][3]': 0, 's[4][0]': 0, 'y[1]': 1, 's[3][2]': 0, 's[10][4]': 0, 's[1][4]': 0, 'x[1][3]': 1, 's[5][3]': 0, 's[3][3]': 0, 'x[1][4]': 0, 'x[1][0]': 1, 's[10][1]': 0, 's[0][3]': 0, 's[2][0]': 0, 's[10][3]': 0, 's[0][1]': 0, 'r_e[2]': 0, 's[5][2]': 0, 'r_e[4]': 0}\n" - ] - } - ], - "source": [ - "import neal\n", - "sa = neal.SimulatedAnnealingSampler()\n", - "sampleset = sa.sample(bqm, num_reads=10)\n", - "decoded_samples = model.decode_sampleset(sampleset)\n", - "best_sample = min(decoded_samples, key=lambda x: x.energy)\n", - "print(best_sample.sample)" - ] - }, - { - "cell_type": "code", - "execution_count": 77, - "id": "daa98042", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "80" - ] - }, - "execution_count": 77, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "(T+number_assets+2)*D+T" - ] - }, { "cell_type": "code", "execution_count": null, @@ -838,14 +765,102 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 96, "id": "a359a291-bbb0-4f4f-97fd-acd5f90d8eb6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'y[9]': 1, 'y[8]': 1, 'y[7]': 1, 'y[0]': 1, 'x[1][2]': 0, 'y[6]': 1, 'x[1][1]': 0, 'x[0][2]': 0, 'x[0][1]': 0, 'x[0][0]': 0, 's[9][4]': 0, 's[9][1]': 0, 's[9][0]': 0, 's[8][3]': 0, 's[8][2]': 0, 's[8][1]': 0, 's[8][0]': 0, 's[7][4]': 0, 's[9][3]': 0, 's[7][3]': 0, 'y[4]': 1, 's[5][1]': 0, 's[6][4]': 0, 's[0][2]': 0, 's[6][0]': 0, 's[0][0]': 0, 's[5][4]': 0, 'x[0][4]': 0, 's[2][3]': 0, 's[5][0]': 0, 'y[3]': 1, 's[4][4]': 0, 'y[2]': 1, 's[8][4]': 0, 's[6][1]': 0, 's[9][2]': 0, 's[4][3]': 0, 'r_e[1]': 0, 's[4][2]': 0, 's[3][4]': 0, 's[3][1]': 0, 'x[0][3]': 0, 's[7][2]': 0, 's[10][0]': 0, 's[4][1]': 0, 'y[5]': 1, 's[3][0]': 0, 's[6][3]': 0, 'r_e[0]': 0, 's[2][4]': 0, 's[7][1]': 0, 's[2][1]': 0, 's[10][2]': 0, 's[1][2]': 0, 's[2][2]': 0, 's[7][0]': 0, 's[6][2]': 0, 's[1][1]': 0, 'r_e[3]': 0, 's[0][4]': 0, 's[1][0]': 0, 's[1][3]': 0, 's[4][0]': 0, 'y[1]': 1, 's[3][2]': 0, 's[10][4]': 0, 's[1][4]': 0, 'x[1][3]': 0, 's[5][3]': 0, 's[3][3]': 0, 'x[1][4]': 1, 'x[1][0]': 0, 's[10][1]': 0, 's[0][3]': 0, 's[2][0]': 0, 's[10][3]': 0, 's[0][1]': 0, 'r_e[2]': 0, 's[5][2]': 0, 'r_e[4]': 0}\n" + ] + } + ], "source": [ - "# write your code here" + "# write your code here\n", + "model = H.compile()\n", + "\n", + "bqm = model.to_bqm()\n", + "import neal\n", + "sa = neal.SimulatedAnnealingSampler()\n", + "sampleset = sa.sample(bqm, num_reads=10)\n", + "decoded_samples = model.decode_sampleset(sampleset)\n", + "best_sample = min(decoded_samples, key=lambda x: x.energy)\n", + "print(best_sample.sample)" ] }, + { + "cell_type": "code", + "execution_count": 99, + "id": "934a51a0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "80" + ] + }, + "execution_count": 99, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "len(best_sample.sample)" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "id": "258d9a77", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "80" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "(T+number_assets+2)*D+T" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "id": "65f97422", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 102, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "best_sample.sample[\"y[9]\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "307dbe26", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "5e4786ea-1db6-46a6-b9f8-d1bfcdb88b20", @@ -872,7 +887,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 124, "id": "95761549", "metadata": {}, "outputs": [], @@ -896,12 +911,97 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 121, "id": "7c6d5972", "metadata": {}, "outputs": [], "source": [ - "# write your code here" + "# write your code here\n", + "\n", + "def cal_asset_i(dict, i, D):\n", + " x_i = 0\n", + " for d in range(D):\n", + " x_i += (1/2**(D-1))*2**(d)*dict[f\"x[{i}][{d}]\"]\n", + " return x_i\n", + "\n", + "def cal_r_e(dict, D, z, Z):\n", + " r_ = 0\n", + " for d in range(D):\n", + " r_ += (1/2**(D-1))*2**(d)*dict[f\"r_e[{d}]\"]\n", + " return -z+(Z+z)*r_" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "id": "dcc4d12a", + "metadata": {}, + "outputs": [], + "source": [ + "def expected_total_returns(expected_returns, number_assets, dict, D):\n", + " total_return = 0\n", + " for i in range(number_assets):\n", + " total_return += expected_returns[i]*cal_asset_i(dict, i, D)\n", + " return total_return" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "id": "c7e71691", + "metadata": {}, + "outputs": [], + "source": [ + "def variance(dict, covariance_matrix, number_assets, D):\n", + " var = 0\n", + " for i in range(number_assets):\n", + " for j in range(number_assets):\n", + " var += covariance_matrix[i, j]*cal_asset_i(dict, i, D)*cal_asset_i(dict, j, D)\n", + " return var" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "id": "e1266b4b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.2" + ] + }, + "execution_count": 122, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "cal_r_e(best_sample.sample, D, z, Z)" + ] + }, + { + "cell_type": "code", + "execution_count": 125, + "id": "e78c8693", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "-0.00024367625150000026" + ] + }, + "execution_count": 125, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "w_ = [cal_asset_i(best_sample.sample, i, D) for i in range(number_assets)]\n", + "\n", + "calculate_historical_VaR(w_, expected_total_returns(expected_returns, number_assets, best_sample.sample, D))" ] }, { From 058a1144745c58ea5b2de1cfae6fd0603324340d Mon Sep 17 00:00:00 2001 From: Lakshika Rathi Date: Sun, 4 Feb 2024 01:37:06 -0500 Subject: [PATCH 06/12] ex4 --- moodys_challenge.ipynb | 350 ++++++++++++++++++++++++++++++++++------- 1 file changed, 296 insertions(+), 54 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index e6a9e6f..2e04ae9 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -332,7 +332,7 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 202, "id": "a78f8aea", "metadata": {}, "outputs": [], @@ -341,8 +341,8 @@ "import pandas as pd\n", "\n", "# You may choose to select different parameters/values\n", - "number_assets = 3\n", - "T = 10\n", + "number_assets = 2\n", + "T = 3\n", "# Read returns\n", "df = pd.read_csv('returns_data.txt',delim_whitespace=True)\n", "\n", @@ -489,21 +489,9 @@ "**Answer:**" ] }, - { - "cell_type": "markdown", - "id": "4cb86004", - "metadata": {}, - "source": [ - "We use the binary encoding for $\\{x_{i}\\}$, which is written as $\\{x_{i}\\}$ = \\[sum_\\]\n", - "\n", - "- Which encoding did you use for each of the variables $\\{x_{i}\\}$, $r_{\\epsilon}$, $\\{y_{t}\\}$, which for the slack variables and why?\n", - "- As you can see, the total number of variables increase after the encoding. What is the total number of binary variables that you have after the mapping?\n", - "- One could cast the problem into a QUBO form, by finding $Q$. Then one can map it to a Hamiltonian by promoting all the binary variables (for example $z_{di}$) to binary operators ($z_{di} \\rightarrow \\hat{z}_{di}$). The Hamiltonian will then have the following form $\\hat{H}=\\hat{z}^{T}Q\\hat{z}$ with $Q \\epsilon \\mathbb{R}^{N \\times N}$ the corresponding QUBO matrix. You do **not** need to find the explicit QUBO form of the Hamiltonian $\\hat{H}$. Instead, substitute the encoding you found in this section to the Langrange formulation of **Section 1** (let's call it $L_{fin}$). Then, use $L_{fin}$ and with the help of [pyqubo](https://pyqubo.readthedocs.io/en/latest/getting_started.html#) find the QUBO formulation of the problem, by finding the matrix $Q$. One could then promote all the variables to operators, to find the quantum version of $L_{fin}$ (let's call it $\\hat{H}$). $L_{fin}$ and $\\hat{H}$ will be used in the following sections." - ] - }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 203, "id": "553d8b31", "metadata": {}, "outputs": [], @@ -521,14 +509,14 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 204, "id": "20b2251c", "metadata": {}, "outputs": [], "source": [ "from pyqubo import Array\n", "\n", - "D = 5\n", + "D = 3\n", "\n", "x = Array.create('x', shape=(number_assets, D), vartype=\"BINARY\")\n", "y = Array.create('y', shape=T, vartype=\"BINARY\")\n", @@ -538,7 +526,7 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 205, "id": "d84cacd7", "metadata": {}, "outputs": [], @@ -565,7 +553,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 206, "id": "a1b3470c", "metadata": {}, "outputs": [], @@ -583,7 +571,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 207, "id": "b05c7c20", "metadata": {}, "outputs": [], @@ -598,7 +586,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 208, "id": "fe40d5ff", "metadata": {}, "outputs": [], @@ -621,7 +609,7 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": 209, "id": "e72ceb1b", "metadata": {}, "outputs": [], @@ -637,7 +625,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": 210, "id": "ff85af2f", "metadata": {}, "outputs": [], @@ -652,7 +640,7 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 211, "id": "ba96d396", "metadata": {}, "outputs": [], @@ -665,14 +653,6 @@ "H = lambda_[0]*H1(covariance_matrix, x)+lambda_[1]*H2(expected_returns, x)+lambda_[2]*H3(r_e, x, R, M, y, s, z, Z)+lambda_[3]*H4(y, T, s, epsilon, D)+lambda_[4]*H5(x)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "92ce9096", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "ed9d5b11-b2f3-4c79-bdf9-000cd7685f85", @@ -765,7 +745,7 @@ }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 212, "id": "a359a291-bbb0-4f4f-97fd-acd5f90d8eb6", "metadata": {}, "outputs": [ @@ -773,7 +753,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'y[9]': 1, 'y[8]': 1, 'y[7]': 1, 'y[0]': 1, 'x[1][2]': 0, 'y[6]': 1, 'x[1][1]': 0, 'x[0][2]': 0, 'x[0][1]': 0, 'x[0][0]': 0, 's[9][4]': 0, 's[9][1]': 0, 's[9][0]': 0, 's[8][3]': 0, 's[8][2]': 0, 's[8][1]': 0, 's[8][0]': 0, 's[7][4]': 0, 's[9][3]': 0, 's[7][3]': 0, 'y[4]': 1, 's[5][1]': 0, 's[6][4]': 0, 's[0][2]': 0, 's[6][0]': 0, 's[0][0]': 0, 's[5][4]': 0, 'x[0][4]': 0, 's[2][3]': 0, 's[5][0]': 0, 'y[3]': 1, 's[4][4]': 0, 'y[2]': 1, 's[8][4]': 0, 's[6][1]': 0, 's[9][2]': 0, 's[4][3]': 0, 'r_e[1]': 0, 's[4][2]': 0, 's[3][4]': 0, 's[3][1]': 0, 'x[0][3]': 0, 's[7][2]': 0, 's[10][0]': 0, 's[4][1]': 0, 'y[5]': 1, 's[3][0]': 0, 's[6][3]': 0, 'r_e[0]': 0, 's[2][4]': 0, 's[7][1]': 0, 's[2][1]': 0, 's[10][2]': 0, 's[1][2]': 0, 's[2][2]': 0, 's[7][0]': 0, 's[6][2]': 0, 's[1][1]': 0, 'r_e[3]': 0, 's[0][4]': 0, 's[1][0]': 0, 's[1][3]': 0, 's[4][0]': 0, 'y[1]': 1, 's[3][2]': 0, 's[10][4]': 0, 's[1][4]': 0, 'x[1][3]': 0, 's[5][3]': 0, 's[3][3]': 0, 'x[1][4]': 1, 'x[1][0]': 0, 's[10][1]': 0, 's[0][3]': 0, 's[2][0]': 0, 's[10][3]': 0, 's[0][1]': 0, 'r_e[2]': 0, 's[5][2]': 0, 'r_e[4]': 0}\n" + "{'x[0][2]': 0, 'y[1]': 1, 's[0][1]': 0, 'x[1][1]': 0, 'x[1][2]': 1, 's[1][0]': 0, 'x[1][0]': 0, 'y[2]': 1, 'x[0][1]': 0, 'x[0][0]': 0, 'y[0]': 1, 's[3][2]': 0, 's[3][1]': 0, 's[3][0]': 0, 's[2][2]': 0, 's[0][2]': 0, 's[2][0]': 0, 's[1][1]': 0, 's[2][1]': 0, 's[0][0]': 0, 'r_e[2]': 0, 'r_e[1]': 0, 's[1][2]': 0, 'r_e[0]': 0}\n" ] } ], @@ -792,38 +772,292 @@ }, { "cell_type": "code", - "execution_count": 99, - "id": "934a51a0", + "execution_count": 213, + "id": "85fd7483", + "metadata": {}, + "outputs": [], + "source": [ + "qubo, _ = model.to_qubo(index_label=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 214, + "id": "0ec77308", + "metadata": {}, + "outputs": [], + "source": [ + "length = len(model.variables)" + ] + }, + { + "cell_type": "code", + "execution_count": 216, + "id": "0f83ce8f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "80" + "24" ] }, - "execution_count": 99, + "execution_count": 216, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "len(best_sample.sample)" + "length" ] }, { "cell_type": "code", - "execution_count": 97, + "execution_count": 215, + "id": "65cb110c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[-7.10114261e-01, 1.00111786e+00, 5.00558932e-01,\n", + " 1.99852733e+00, 9.99263665e-01, 4.99631832e-01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -4.49218760e-01, -1.35790494e-01, 2.95275600e-01,\n", + " 1.79687504e-01, 8.98437520e-02, 4.49218760e-02,\n", + " 2.95528327e-01, 1.47764164e-01, 7.38820818e-02,\n", + " 5.43161976e-02, 2.71580988e-02, 1.35790494e-02,\n", + " -1.18110240e-01, -5.90551200e-02, -2.95275600e-02],\n", + " [ 0.00000000e+00, -6.05336597e-01, 2.50279466e-01,\n", + " 9.99263665e-01, 4.99631832e-01, 2.49815916e-01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -2.24609380e-01, -6.78952470e-02, 1.47637800e-01,\n", + " 8.98437520e-02, 4.49218760e-02, 2.24609380e-02,\n", + " 1.47764164e-01, 7.38820818e-02, 3.69410409e-02,\n", + " 2.71580988e-02, 1.35790494e-02, 6.78952470e-03,\n", + " -5.90551200e-02, -2.95275600e-02, -1.47637800e-02],\n", + " [ 0.00000000e+00, 0.00000000e+00, -3.65238165e-01,\n", + " 4.99631832e-01, 2.49815916e-01, 1.24907958e-01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -1.12304690e-01, -3.39476235e-02, 7.38189000e-02,\n", + " 4.49218760e-02, 2.24609380e-02, 1.12304690e-02,\n", + " 7.38820818e-02, 3.69410409e-02, 1.84705204e-02,\n", + " 1.35790494e-02, 6.78952470e-03, 3.39476235e-03,\n", + " -2.95275600e-02, -1.47637800e-02, -7.38189000e-03],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -2.06711601e+00, 1.00272503e+00, 5.01362517e-01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 2.15936080e-01, 8.98014440e-01, -4.05314120e-02,\n", + " -8.63744320e-02, -4.31872160e-02, -2.15936080e-02,\n", + " -1.09488749e+00, -5.47443745e-01, -2.73721873e-01,\n", + " -3.59205776e-01, -1.79602888e-01, -8.98014440e-02,\n", + " 1.62125648e-02, 8.10628240e-03, 4.05314120e-03],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, -1.28423926e+00, 2.50681258e-01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 1.07968040e-01, 4.49007220e-01, -2.02657060e-02,\n", + " -4.31872160e-02, -2.15936080e-02, -1.07968040e-02,\n", + " -5.47443745e-01, -2.73721873e-01, -1.36860936e-01,\n", + " -1.79602888e-01, -8.98014440e-02, -4.49007220e-02,\n", + " 8.10628240e-03, 4.05314120e-03, 2.02657060e-03],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, -7.04789946e-01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 5.39840200e-02, 2.24503610e-01, -1.01328530e-02,\n", + " -2.15936080e-02, -1.07968040e-02, -5.39840200e-03,\n", + " -2.73721873e-01, -1.36860936e-01, -6.84304681e-02,\n", + " -8.98014440e-02, -4.49007220e-02, -2.24503610e-02,\n", + " 4.05314120e-03, 2.02657060e-03, 1.01328530e-03],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 3.88000000e+01, 1.60000000e+01, 8.00000000e+00,\n", + " -8.00000000e+00, -8.00000000e+00, -8.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 1.54000000e+01, 4.00000000e+00,\n", + " -4.00000000e+00, -4.00000000e+00, -4.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 6.70000000e+00,\n", + " -2.00000000e+00, -2.00000000e+00, -2.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -1.00700000e+02, 2.00000000e+00, 2.00000000e+00,\n", + " -8.00000000e+01, -4.00000000e+01, -2.00000000e+01,\n", + " -2.04000000e+02, -1.02000000e+02, -5.10000000e+01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, -1.00700000e+02, 2.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -2.04000000e+02, -1.02000000e+02, -5.10000000e+01,\n", + " -8.00000000e+01, -4.00000000e+01, -2.00000000e+01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, -1.00700000e+02,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -2.04000000e+02, -1.02000000e+02, -5.10000000e+01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " -8.00000000e+01, -4.00000000e+01, -2.00000000e+01],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 9.44000000e+01, 1.60000000e+01, 8.00000000e+00,\n", + " 8.16000000e+01, 4.08000000e+01, 2.04000000e+01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 4.32000000e+01, 4.00000000e+00,\n", + " 4.08000000e+01, 2.04000000e+01, 1.02000000e+01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 2.06000000e+01,\n", + " 2.04000000e+01, 1.02000000e+01, 5.10000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 9.11880000e+02, 3.12120000e+02, 1.56060000e+02,\n", + " 8.16000000e+01, 4.08000000e+01, 2.04000000e+01,\n", + " 8.16000000e+01, 4.08000000e+01, 2.04000000e+01],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 3.77910000e+02, 7.80300000e+01,\n", + " 4.08000000e+01, 2.04000000e+01, 1.02000000e+01,\n", + " 4.08000000e+01, 2.04000000e+01, 1.02000000e+01],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 1.69447500e+02,\n", + " 2.04000000e+01, 1.02000000e+01, 5.10000000e+00,\n", + " 2.04000000e+01, 1.02000000e+01, 5.10000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 9.44000000e+01, 1.60000000e+01, 8.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 4.32000000e+01, 4.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 2.06000000e+01,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 9.44000000e+01, 1.60000000e+01, 8.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 4.32000000e+01, 4.00000000e+00],\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " 0.00000000e+00, 0.00000000e+00, 2.06000000e+01]])" + ] + }, + "execution_count": 215, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "qubo_matrix = np.zeros((length,length))\n", + "for key, value in qubo.items():\n", + " qubo_matrix[key[0],key[1]] = value\n", + "qubo_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 196, + "id": "d80ba175", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict" + ] + }, + "execution_count": 196, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 162, "id": "258d9a77", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "80" + "55" ] }, - "execution_count": 97, + "execution_count": 162, "metadata": {}, "output_type": "execute_result" } @@ -834,7 +1068,7 @@ }, { "cell_type": "code", - "execution_count": 102, + "execution_count": 163, "id": "65f97422", "metadata": {}, "outputs": [ @@ -844,7 +1078,7 @@ "1" ] }, - "execution_count": 102, + "execution_count": 163, "metadata": {}, "output_type": "execute_result" } @@ -887,7 +1121,7 @@ }, { "cell_type": "code", - "execution_count": 124, + "execution_count": 164, "id": "95761549", "metadata": {}, "outputs": [], @@ -911,7 +1145,7 @@ }, { "cell_type": "code", - "execution_count": 121, + "execution_count": 165, "id": "7c6d5972", "metadata": {}, "outputs": [], @@ -933,7 +1167,7 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": 166, "id": "dcc4d12a", "metadata": {}, "outputs": [], @@ -947,7 +1181,7 @@ }, { "cell_type": "code", - "execution_count": 119, + "execution_count": 167, "id": "c7e71691", "metadata": {}, "outputs": [], @@ -962,7 +1196,7 @@ }, { "cell_type": "code", - "execution_count": 122, + "execution_count": 168, "id": "e1266b4b", "metadata": {}, "outputs": [ @@ -972,7 +1206,7 @@ "-0.2" ] }, - "execution_count": 122, + "execution_count": 168, "metadata": {}, "output_type": "execute_result" } @@ -983,17 +1217,17 @@ }, { "cell_type": "code", - "execution_count": 125, + "execution_count": 169, "id": "e78c8693", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "-0.00024367625150000026" + "0.0013588666650000004" ] }, - "execution_count": 125, + "execution_count": 169, "metadata": {}, "output_type": "execute_result" } @@ -1058,6 +1292,14 @@ "No matter what algorithm you choose, **you are encouraged to run small-scale simulations of the problems on quantum backends and simulators, always keeping in mind the resources that you are utilizing and their cost**. What problems/limitations do you encounter in comparison with simulated annealing?" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf0bf994", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "dbc17d65-627d-4805-ac9f-3a3803bfc70d", From 7f39a0707caef25d47048e27b87ed46a464a8bf5 Mon Sep 17 00:00:00 2001 From: Lizard Empress Date: Sun, 4 Feb 2024 02:19:29 -0500 Subject: [PATCH 07/12] stochastic simulation for z estimate and M initial estimate from literature --- moodys_challenge.ipynb | 103 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 97 insertions(+), 6 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index ada2943..c7b9fdf 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -321,12 +321,13 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "d76f8c15", "metadata": {}, "outputs": [], "source": [ - "#!pip install -r requirements.txt" + "#!pip install -r requirements.txt\n", + "import math" ] }, { @@ -342,14 +343,34 @@ }, { "cell_type": "code", - "execution_count": 202, - "id": "a78f8aea", + "execution_count": 6, + "id": "22b84c06", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd\n", - "\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a78f8aea", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "<>:5: SyntaxWarning: invalid escape sequence '\\s'\n", + "<>:5: SyntaxWarning: invalid escape sequence '\\s'\n", + "C:\\Users\\345li\\AppData\\Local\\Temp\\ipykernel_18932\\2293168254.py:5: SyntaxWarning: invalid escape sequence '\\s'\n", + " df = pd.read_csv('returns_data.txt', sep='\\s+')\n" + ] + } + ], + "source": [ "# You may choose to select different parameters/values\n", "number_assets = 2\n", "T = 3\n", @@ -416,6 +437,76 @@ "$$" ] }, + { + "cell_type": "code", + "execution_count": 16, + "id": "377db1df", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "-0.016702926904596967 0.0025621792052936266\n", + "z is 0.016702926904596967\n" + ] + } + ], + "source": [ + "# getting experimental estimates for z\n", + "min_r_epsilon_simulated = math.inf\n", + "max_r_epsilon_simulated = -math.inf\n", + "simulation_count = 0\n", + "\n", + "samps = np.random.random(number_assets)\n", + "weights = samps/np.sum(samps)\n", + "confidence_level = 0.95\n", + "r_e_vals = []\n", + "\n", + "# get expected asset returns (vectorized)\n", + "expected_asset_returns = np.mean(R, axis=1) # row averages\n", + "\n", + "while simulation_count < 100:\n", + " portfolio_returns = np.dot(expected_asset_returns, np.transpose(np.array(weights)))\n", + " VaR = np.percentile(portfolio_returns, 100 * (1 - confidence_level))\n", + " # print(\"-VaR\", -VaR)\n", + " r_e_vals.append(-VaR)\n", + " \n", + " samps = np.random.random(number_assets)\n", + " weights = samps/np.sum(samps)\n", + " simulation_count += 1\n", + "\n", + "# print(r_e_vals)\n", + "print(min(r_e_vals), max(r_e_vals))\n", + "z = -min(r_e_vals)\n", + "print(\"z is\", z)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "9eb5197e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.005758011095403033" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# initial estimates for M_ideal_tilde from paper (pre-solution x_k*)\n", + "# from https://link.springer.com/article/10.1007/s00291-023-00719-x\n", + "M_ideal_tilde = -z-np.min(R)\n", + "\n", + "M_ideal_tilde" + ] + }, { "cell_type": "markdown", "id": "bb2982bd-fbb9-49de-8dbc-370e9390173b", @@ -1493,7 +1584,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.12.1" }, "vscode": { "interpreter": { From fbfb8249e148a1e4de22ccbd016890f00940b457 Mon Sep 17 00:00:00 2001 From: Preetham Tikkireddi Date: Sun, 4 Feb 2024 07:45:37 -0600 Subject: [PATCH 08/12] cleanup --- moodys_challenge.ipynb | 316 ++++++++--------------------------------- 1 file changed, 57 insertions(+), 259 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index c7b9fdf..4677eb4 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -321,13 +321,12 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "d76f8c15", "metadata": {}, "outputs": [], "source": [ - "#!pip install -r requirements.txt\n", - "import math" + "#!pip install -r requirements.txt" ] }, { @@ -343,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 1, "id": "22b84c06", "metadata": {}, "outputs": [], @@ -355,25 +354,14 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 2, "id": "a78f8aea", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "<>:5: SyntaxWarning: invalid escape sequence '\\s'\n", - "<>:5: SyntaxWarning: invalid escape sequence '\\s'\n", - "C:\\Users\\345li\\AppData\\Local\\Temp\\ipykernel_18932\\2293168254.py:5: SyntaxWarning: invalid escape sequence '\\s'\n", - " df = pd.read_csv('returns_data.txt', sep='\\s+')\n" - ] - } - ], + "outputs": [], "source": [ "# You may choose to select different parameters/values\n", - "number_assets = 2\n", - "T = 3\n", + "number_assets = 3\n", + "T = 10\n", "# Read returns\n", "df = pd.read_csv('returns_data.txt', sep='\\s+')\n", "\n", @@ -439,7 +427,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 3, "id": "377db1df", "metadata": {}, "outputs": [ @@ -447,8 +435,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "-0.016702926904596967 0.0025621792052936266\n", - "z is 0.016702926904596967\n" + "-0.009770171700139656 -0.00043712232753584834\n", + "z is 0.009770171700139656\n" ] } ], @@ -484,17 +472,17 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 4, "id": "9eb5197e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "0.005758011095403033" + "0.07854994329986034" ] }, - "execution_count": 17, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -637,7 +625,7 @@ }, { "cell_type": "code", - "execution_count": 203, + "execution_count": 30, "id": "553d8b31", "metadata": {}, "outputs": [], @@ -655,7 +643,7 @@ }, { "cell_type": "code", - "execution_count": 204, + "execution_count": 5, "id": "20b2251c", "metadata": {}, "outputs": [], @@ -672,7 +660,7 @@ }, { "cell_type": "code", - "execution_count": 205, + "execution_count": 6, "id": "d84cacd7", "metadata": {}, "outputs": [], @@ -699,7 +687,7 @@ }, { "cell_type": "code", - "execution_count": 206, + "execution_count": 7, "id": "a1b3470c", "metadata": {}, "outputs": [], @@ -717,7 +705,7 @@ }, { "cell_type": "code", - "execution_count": 207, + "execution_count": 8, "id": "b05c7c20", "metadata": {}, "outputs": [], @@ -732,7 +720,7 @@ }, { "cell_type": "code", - "execution_count": 208, + "execution_count": 9, "id": "fe40d5ff", "metadata": {}, "outputs": [], @@ -755,7 +743,7 @@ }, { "cell_type": "code", - "execution_count": 209, + "execution_count": 10, "id": "e72ceb1b", "metadata": {}, "outputs": [], @@ -771,7 +759,7 @@ }, { "cell_type": "code", - "execution_count": 210, + "execution_count": 11, "id": "ff85af2f", "metadata": {}, "outputs": [], @@ -786,7 +774,7 @@ }, { "cell_type": "code", - "execution_count": 211, + "execution_count": 12, "id": "ba96d396", "metadata": {}, "outputs": [], @@ -891,7 +879,7 @@ }, { "cell_type": "code", - "execution_count": 212, + "execution_count": 13, "id": "a359a291-bbb0-4f4f-97fd-acd5f90d8eb6", "metadata": {}, "outputs": [ @@ -899,7 +887,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'x[0][2]': 0, 'y[1]': 1, 's[0][1]': 0, 'x[1][1]': 0, 'x[1][2]': 1, 's[1][0]': 0, 'x[1][0]': 0, 'y[2]': 1, 'x[0][1]': 0, 'x[0][0]': 0, 'y[0]': 1, 's[3][2]': 0, 's[3][1]': 0, 's[3][0]': 0, 's[2][2]': 0, 's[0][2]': 0, 's[2][0]': 0, 's[1][1]': 0, 's[2][1]': 0, 's[0][0]': 0, 'r_e[2]': 0, 'r_e[1]': 0, 's[1][2]': 0, 'r_e[0]': 0}\n" + "{'y[9]': 1, 'y[8]': 1, 'y[6]': 1, 'y[3]': 1, 'y[2]': 1, 'y[1]': 1, 'y[0]': 1, 'x[0][1]': 0, 'x[0][0]': 0, 's[9][2]': 0, 's[9][0]': 0, 's[8][0]': 0, 's[7][2]': 0, 'x[2][0]': 0, 's[2][0]': 0, 's[1][2]': 0, 's[10][1]': 0, 's[5][2]': 0, 'r_e[2]': 0, 'y[4]': 1, 'x[1][2]': 0, 's[0][2]': 0, 's[1][0]': 0, 'r_e[0]': 0, 's[10][2]': 0, 's[5][0]': 0, 's[0][1]': 0, 's[8][1]': 0, 's[2][2]': 0, 's[7][0]': 0, 's[1][1]': 0, 's[0][0]': 0, 'y[7]': 1, 's[2][1]': 0, 'x[0][2]': 0, 's[10][0]': 0, 's[3][0]': 0, 'x[1][1]': 0, 's[3][2]': 0, 's[6][0]': 0, 's[5][1]': 0, 'r_e[1]': 0, 's[3][1]': 0, 's[4][0]': 0, 'x[2][1]': 0, 'x[1][0]': 0, 's[7][1]': 0, 's[4][1]': 0, 's[9][1]': 0, 's[8][2]': 0, 's[4][2]': 0, 'y[5]': 1, 'x[2][2]': 1, 's[6][1]': 0, 's[6][2]': 0}\n" ] } ], @@ -918,7 +906,7 @@ }, { "cell_type": "code", - "execution_count": 213, + "execution_count": 14, "id": "85fd7483", "metadata": {}, "outputs": [], @@ -928,7 +916,7 @@ }, { "cell_type": "code", - "execution_count": 214, + "execution_count": 15, "id": "0ec77308", "metadata": {}, "outputs": [], @@ -938,17 +926,17 @@ }, { "cell_type": "code", - "execution_count": 216, + "execution_count": 16, "id": "0f83ce8f", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "24" + "55" ] }, - "execution_count": 216, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -959,208 +947,29 @@ }, { "cell_type": "code", - "execution_count": 215, + "execution_count": 17, "id": "65cb110c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[-7.10114261e-01, 1.00111786e+00, 5.00558932e-01,\n", - " 1.99852733e+00, 9.99263665e-01, 4.99631832e-01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -4.49218760e-01, -1.35790494e-01, 2.95275600e-01,\n", - " 1.79687504e-01, 8.98437520e-02, 4.49218760e-02,\n", - " 2.95528327e-01, 1.47764164e-01, 7.38820818e-02,\n", - " 5.43161976e-02, 2.71580988e-02, 1.35790494e-02,\n", - " -1.18110240e-01, -5.90551200e-02, -2.95275600e-02],\n", - " [ 0.00000000e+00, -6.05336597e-01, 2.50279466e-01,\n", - " 9.99263665e-01, 4.99631832e-01, 2.49815916e-01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -2.24609380e-01, -6.78952470e-02, 1.47637800e-01,\n", - " 8.98437520e-02, 4.49218760e-02, 2.24609380e-02,\n", - " 1.47764164e-01, 7.38820818e-02, 3.69410409e-02,\n", - " 2.71580988e-02, 1.35790494e-02, 6.78952470e-03,\n", - " -5.90551200e-02, -2.95275600e-02, -1.47637800e-02],\n", - " [ 0.00000000e+00, 0.00000000e+00, -3.65238165e-01,\n", - " 4.99631832e-01, 2.49815916e-01, 1.24907958e-01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -1.12304690e-01, -3.39476235e-02, 7.38189000e-02,\n", - " 4.49218760e-02, 2.24609380e-02, 1.12304690e-02,\n", - " 7.38820818e-02, 3.69410409e-02, 1.84705204e-02,\n", - " 1.35790494e-02, 6.78952470e-03, 3.39476235e-03,\n", - " -2.95275600e-02, -1.47637800e-02, -7.38189000e-03],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -2.06711601e+00, 1.00272503e+00, 5.01362517e-01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 2.15936080e-01, 8.98014440e-01, -4.05314120e-02,\n", - " -8.63744320e-02, -4.31872160e-02, -2.15936080e-02,\n", - " -1.09488749e+00, -5.47443745e-01, -2.73721873e-01,\n", - " -3.59205776e-01, -1.79602888e-01, -8.98014440e-02,\n", - " 1.62125648e-02, 8.10628240e-03, 4.05314120e-03],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, -1.28423926e+00, 2.50681258e-01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 1.07968040e-01, 4.49007220e-01, -2.02657060e-02,\n", - " -4.31872160e-02, -2.15936080e-02, -1.07968040e-02,\n", - " -5.47443745e-01, -2.73721873e-01, -1.36860936e-01,\n", - " -1.79602888e-01, -8.98014440e-02, -4.49007220e-02,\n", - " 8.10628240e-03, 4.05314120e-03, 2.02657060e-03],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, -7.04789946e-01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 5.39840200e-02, 2.24503610e-01, -1.01328530e-02,\n", - " -2.15936080e-02, -1.07968040e-02, -5.39840200e-03,\n", - " -2.73721873e-01, -1.36860936e-01, -6.84304681e-02,\n", - " -8.98014440e-02, -4.49007220e-02, -2.24503610e-02,\n", - " 4.05314120e-03, 2.02657060e-03, 1.01328530e-03],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 3.88000000e+01, 1.60000000e+01, 8.00000000e+00,\n", - " -8.00000000e+00, -8.00000000e+00, -8.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 1.54000000e+01, 4.00000000e+00,\n", - " -4.00000000e+00, -4.00000000e+00, -4.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 6.70000000e+00,\n", - " -2.00000000e+00, -2.00000000e+00, -2.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -1.00700000e+02, 2.00000000e+00, 2.00000000e+00,\n", - " -8.00000000e+01, -4.00000000e+01, -2.00000000e+01,\n", - " -2.04000000e+02, -1.02000000e+02, -5.10000000e+01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, -1.00700000e+02, 2.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -2.04000000e+02, -1.02000000e+02, -5.10000000e+01,\n", - " -8.00000000e+01, -4.00000000e+01, -2.00000000e+01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, -1.00700000e+02,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -2.04000000e+02, -1.02000000e+02, -5.10000000e+01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " -8.00000000e+01, -4.00000000e+01, -2.00000000e+01],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 9.44000000e+01, 1.60000000e+01, 8.00000000e+00,\n", - " 8.16000000e+01, 4.08000000e+01, 2.04000000e+01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 4.32000000e+01, 4.00000000e+00,\n", - " 4.08000000e+01, 2.04000000e+01, 1.02000000e+01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 2.06000000e+01,\n", - " 2.04000000e+01, 1.02000000e+01, 5.10000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 9.11880000e+02, 3.12120000e+02, 1.56060000e+02,\n", - " 8.16000000e+01, 4.08000000e+01, 2.04000000e+01,\n", - " 8.16000000e+01, 4.08000000e+01, 2.04000000e+01],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 3.77910000e+02, 7.80300000e+01,\n", - " 4.08000000e+01, 2.04000000e+01, 1.02000000e+01,\n", - " 4.08000000e+01, 2.04000000e+01, 1.02000000e+01],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 1.69447500e+02,\n", - " 2.04000000e+01, 1.02000000e+01, 5.10000000e+00,\n", - " 2.04000000e+01, 1.02000000e+01, 5.10000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 9.44000000e+01, 1.60000000e+01, 8.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 4.32000000e+01, 4.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 2.06000000e+01,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + "array([[-6.90402399e-01, 1.01215679e+00, 5.06078393e-01, ...,\n", + " 4.61927104e-02, 2.30963552e-02, 1.15481776e-02],\n", + " [ 0.00000000e+00, -5.98240396e-01, 2.53039197e-01, ...,\n", + " 2.30963552e-02, 1.15481776e-02, 5.77408880e-03],\n", + " [ 0.00000000e+00, 0.00000000e+00, -3.62379997e-01, ...,\n", + " 1.15481776e-02, 5.77408880e-03, 2.88704440e-03],\n", + " ...,\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,\n", " 9.44000000e+01, 1.60000000e+01, 8.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,\n", " 0.00000000e+00, 4.32000000e+01, 4.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", - " 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,\n", + " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,\n", " 0.00000000e+00, 0.00000000e+00, 2.06000000e+01]])" ] }, - "execution_count": 215, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -1174,26 +983,15 @@ }, { "cell_type": "code", - "execution_count": 196, + "execution_count": null, "id": "d80ba175", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "dict" - ] - }, - "execution_count": 196, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [] }, { "cell_type": "code", - "execution_count": 162, + "execution_count": 18, "id": "258d9a77", "metadata": {}, "outputs": [ @@ -1203,7 +1001,7 @@ "55" ] }, - "execution_count": 162, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } @@ -1214,7 +1012,7 @@ }, { "cell_type": "code", - "execution_count": 163, + "execution_count": 19, "id": "65f97422", "metadata": {}, "outputs": [ @@ -1224,7 +1022,7 @@ "1" ] }, - "execution_count": 163, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -1267,7 +1065,7 @@ }, { "cell_type": "code", - "execution_count": 164, + "execution_count": 20, "id": "95761549", "metadata": {}, "outputs": [], @@ -1291,7 +1089,7 @@ }, { "cell_type": "code", - "execution_count": 165, + "execution_count": 21, "id": "7c6d5972", "metadata": {}, "outputs": [], @@ -1313,7 +1111,7 @@ }, { "cell_type": "code", - "execution_count": 166, + "execution_count": 22, "id": "dcc4d12a", "metadata": {}, "outputs": [], @@ -1327,7 +1125,7 @@ }, { "cell_type": "code", - "execution_count": 167, + "execution_count": 23, "id": "c7e71691", "metadata": {}, "outputs": [], @@ -1342,7 +1140,7 @@ }, { "cell_type": "code", - "execution_count": 168, + "execution_count": 24, "id": "e1266b4b", "metadata": {}, "outputs": [ @@ -1352,7 +1150,7 @@ "-0.2" ] }, - "execution_count": 168, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -1363,7 +1161,7 @@ }, { "cell_type": "code", - "execution_count": 169, + "execution_count": 25, "id": "e78c8693", "metadata": {}, "outputs": [ @@ -1373,7 +1171,7 @@ "0.0013588666650000004" ] }, - "execution_count": 169, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -1570,7 +1368,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3.9.6 64-bit", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1584,7 +1382,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.1" + "version": "3.11.6" }, "vscode": { "interpreter": { From c4604ce46aa4cbd92662ce0d79c65879a459ff8b Mon Sep 17 00:00:00 2001 From: Lakshika Rathi Date: Sun, 4 Feb 2024 09:17:49 -0500 Subject: [PATCH 09/12] final changes --- moodys_challenge.ipynb | 383 ++++++++++++++++------------------------- 1 file changed, 146 insertions(+), 237 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index 4677eb4..b260a32 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -321,7 +321,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "d76f8c15", "metadata": {}, "outputs": [], @@ -342,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 3, "id": "22b84c06", "metadata": {}, "outputs": [], @@ -354,7 +354,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 4, "id": "a78f8aea", "metadata": {}, "outputs": [], @@ -405,6 +405,14 @@ "" ] }, + { + "cell_type": "markdown", + "id": "2a1bc476", + "metadata": {}, + "source": [ + "===========================================================================================================================" + ] + }, { "cell_type": "markdown", "id": "23645c2f-0916-477e-9cf8-2ecb6ed114d1", @@ -427,7 +435,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "id": "377db1df", "metadata": {}, "outputs": [ @@ -435,8 +443,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "-0.009770171700139656 -0.00043712232753584834\n", - "z is 0.009770171700139656\n" + "-0.009014860124848744 4.204611377330599e-05\n", + "z is 0.009014860124848744\n" ] } ], @@ -472,19 +480,16 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 7, "id": "9eb5197e", "metadata": {}, "outputs": [ { - "data": { - "text/plain": [ - "0.07854994329986034" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" + "name": "stdout", + "output_type": "stream", + "text": [ + "M_ideal_tilde is 0.07930525487515126\n" + ] } ], "source": [ @@ -492,7 +497,7 @@ "# from https://link.springer.com/article/10.1007/s00291-023-00719-x\n", "M_ideal_tilde = -z-np.min(R)\n", "\n", - "M_ideal_tilde" + "print(\"M_ideal_tilde is\", M_ideal_tilde)" ] }, { @@ -582,6 +587,22 @@ "" ] }, + { + "cell_type": "markdown", + "id": "7ea5d7a5", + "metadata": {}, + "source": [ + "===========================================================================================================================" + ] + }, + { + "cell_type": "markdown", + "id": "897a8e15-2da5-4ae2-9108-31aa005d6057", + "metadata": {}, + "source": [ + "**Answer:**" + ] + }, { "cell_type": "markdown", "id": "a0f4be8f", @@ -605,45 +626,19 @@ "\n", "where $-z$ is the minimum for $r_{\\epsilon}$. \n", "\n", - "And $r_{\\epsilon}' = \\sum_{d = 1}^{D} \\frac{1}{2^{D-1}}2^{d-1} z_{di} $ is the normalized version, there are $D$ of them \n", + "And $r_{\\epsilon}' = \\sum_{d = 1}^{D} \\frac{1}{2^{D-1}}2^{d-1} z_{di} $ is the normalized version, there are $D$ binary variables for that.\n", "\n", "
\n", "\n", - "$S = \\sum_{d = 1}^{D}2^{d-1}S_d$ and there are $(T+1) D$ of these\n", + "$S = \\sum_{d = 1}^{D}2^{d-1}S_d$ and there are $(T+1) D$ of these slack variables.\n", "\n", "\n", "So total number of variables is $D(n + T + 2) + T$\n" ] }, - { - "cell_type": "markdown", - "id": "897a8e15-2da5-4ae2-9108-31aa005d6057", - "metadata": {}, - "source": [ - "**Answer:**" - ] - }, { "cell_type": "code", - "execution_count": 30, - "id": "553d8b31", - "metadata": {}, - "outputs": [], - "source": [ - "# write your code here" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "46350de7", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 5, + "execution_count": 10, "id": "20b2251c", "metadata": {}, "outputs": [], @@ -660,7 +655,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 11, "id": "d84cacd7", "metadata": {}, "outputs": [], @@ -687,7 +682,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 12, "id": "a1b3470c", "metadata": {}, "outputs": [], @@ -705,7 +700,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 13, "id": "b05c7c20", "metadata": {}, "outputs": [], @@ -720,7 +715,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 14, "id": "fe40d5ff", "metadata": {}, "outputs": [], @@ -743,7 +738,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 15, "id": "e72ceb1b", "metadata": {}, "outputs": [], @@ -759,7 +754,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 16, "id": "ff85af2f", "metadata": {}, "outputs": [], @@ -774,7 +769,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 17, "id": "ba96d396", "metadata": {}, "outputs": [], @@ -800,14 +795,6 @@ "" ] }, - { - "cell_type": "markdown", - "id": "51466cca-e371-4f55-bdee-7b2eea6159d8", - "metadata": {}, - "source": [ - "**Answer:**" - ] - }, { "cell_type": "markdown", "id": "9344d008-0e1a-45fd-9aa3-1399e56b859c", @@ -877,9 +864,17 @@ "" ] }, + { + "cell_type": "markdown", + "id": "cf4d509a", + "metadata": {}, + "source": [ + "===========================================================================================================================" + ] + }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 18, "id": "a359a291-bbb0-4f4f-97fd-acd5f90d8eb6", "metadata": {}, "outputs": [ @@ -887,7 +882,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "{'y[9]': 1, 'y[8]': 1, 'y[6]': 1, 'y[3]': 1, 'y[2]': 1, 'y[1]': 1, 'y[0]': 1, 'x[0][1]': 0, 'x[0][0]': 0, 's[9][2]': 0, 's[9][0]': 0, 's[8][0]': 0, 's[7][2]': 0, 'x[2][0]': 0, 's[2][0]': 0, 's[1][2]': 0, 's[10][1]': 0, 's[5][2]': 0, 'r_e[2]': 0, 'y[4]': 1, 'x[1][2]': 0, 's[0][2]': 0, 's[1][0]': 0, 'r_e[0]': 0, 's[10][2]': 0, 's[5][0]': 0, 's[0][1]': 0, 's[8][1]': 0, 's[2][2]': 0, 's[7][0]': 0, 's[1][1]': 0, 's[0][0]': 0, 'y[7]': 1, 's[2][1]': 0, 'x[0][2]': 0, 's[10][0]': 0, 's[3][0]': 0, 'x[1][1]': 0, 's[3][2]': 0, 's[6][0]': 0, 's[5][1]': 0, 'r_e[1]': 0, 's[3][1]': 0, 's[4][0]': 0, 'x[2][1]': 0, 'x[1][0]': 0, 's[7][1]': 0, 's[4][1]': 0, 's[9][1]': 0, 's[8][2]': 0, 's[4][2]': 0, 'y[5]': 1, 'x[2][2]': 1, 's[6][1]': 0, 's[6][2]': 0}\n" + "{'y[9]': 1, 'y[8]': 1, 'y[7]': 1, 'y[3]': 1, 'x[2][2]': 0, 's[3][2]': 0, 'y[1]': 1, 'x[0][2]': 0, 'x[0][1]': 0, 'x[0][0]': 0, 'x[2][0]': 1, 's[9][2]': 0, 's[8][2]': 0, 's[10][0]': 1, 's[4][1]': 0, 's[7][2]': 0, 'y[2]': 1, 's[6][1]': 0, 's[0][2]': 0, 's[6][0]': 0, 's[5][2]': 0, 'y[5]': 1, 's[3][0]': 0, 'y[0]': 1, 's[4][0]': 0, 's[5][0]': 0, 's[8][0]': 0, 'r_e[1]': 0, 's[4][2]': 0, 's[7][0]': 0, 's[2][2]': 0, 's[9][0]': 0, 'x[2][1]': 1, 's[7][1]': 0, 's[2][1]': 0, 'y[4]': 1, 's[5][1]': 0, 's[10][2]': 0, 's[1][2]': 0, 's[6][2]': 0, 's[1][1]': 0, 's[3][1]': 0, 'x[1][0]': 1, 's[10][1]': 0, 's[2][0]': 0, 's[1][0]': 0, 'x[1][2]': 0, 'y[6]': 1, 'x[1][1]': 0, 's[9][1]': 0, 's[0][1]': 0, 's[0][0]': 0, 's[8][1]': 0, 'r_e[2]': 0, 'r_e[0]': 0}\n" ] } ], @@ -906,7 +901,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 19, "id": "85fd7483", "metadata": {}, "outputs": [], @@ -916,82 +911,7 @@ }, { "cell_type": "code", - "execution_count": 15, - "id": "0ec77308", - "metadata": {}, - "outputs": [], - "source": [ - "length = len(model.variables)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "0f83ce8f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "55" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "length" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "65cb110c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[-6.90402399e-01, 1.01215679e+00, 5.06078393e-01, ...,\n", - " 4.61927104e-02, 2.30963552e-02, 1.15481776e-02],\n", - " [ 0.00000000e+00, -5.98240396e-01, 2.53039197e-01, ...,\n", - " 2.30963552e-02, 1.15481776e-02, 5.77408880e-03],\n", - " [ 0.00000000e+00, 0.00000000e+00, -3.62379997e-01, ...,\n", - " 1.15481776e-02, 5.77408880e-03, 2.88704440e-03],\n", - " ...,\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,\n", - " 9.44000000e+01, 1.60000000e+01, 8.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,\n", - " 0.00000000e+00, 4.32000000e+01, 4.00000000e+00],\n", - " [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, ...,\n", - " 0.00000000e+00, 0.00000000e+00, 2.06000000e+01]])" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "qubo_matrix = np.zeros((length,length))\n", - "for key, value in qubo.items():\n", - " qubo_matrix[key[0],key[1]] = value\n", - "qubo_matrix" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d80ba175", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 18, + "execution_count": 20, "id": "258d9a77", "metadata": {}, "outputs": [ @@ -1001,7 +921,7 @@ "55" ] }, - "execution_count": 18, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -1010,35 +930,6 @@ "(T+number_assets+2)*D+T" ] }, - { - "cell_type": "code", - "execution_count": 19, - "id": "65f97422", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "best_sample.sample[\"y[9]\"]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "307dbe26", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "5e4786ea-1db6-46a6-b9f8-d1bfcdb88b20", @@ -1065,7 +956,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 21, "id": "95761549", "metadata": {}, "outputs": [], @@ -1087,15 +978,22 @@ "with $\\textit{weights}$ being a list that includes the optimal values (your solution) for the variables $\\{x_{i}\\}$ and $\\textit{mu_R}$ the expected returns of the assets (given by the data). Compare the return value got from this function to $VaR_{\\epsilon}$ calculated above." ] }, + { + "cell_type": "markdown", + "id": "7b9f3fdd", + "metadata": {}, + "source": [ + "===========================================================================================================================" + ] + }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "id": "7c6d5972", "metadata": {}, "outputs": [], "source": [ "# write your code here\n", - "\n", "def cal_asset_i(dict, i, D):\n", " x_i = 0\n", " for d in range(D):\n", @@ -1111,7 +1009,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "id": "dcc4d12a", "metadata": {}, "outputs": [], @@ -1125,7 +1023,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "id": "c7e71691", "metadata": {}, "outputs": [], @@ -1138,58 +1036,6 @@ " return var" ] }, - { - "cell_type": "code", - "execution_count": 24, - "id": "e1266b4b", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-0.2" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "cal_r_e(best_sample.sample, D, z, Z)" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "id": "e78c8693", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.0013588666650000004" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "w_ = [cal_asset_i(best_sample.sample, i, D) for i in range(number_assets)]\n", - "\n", - "calculate_historical_VaR(w_, expected_total_returns(expected_returns, number_assets, best_sample.sample, D))" - ] - }, - { - "cell_type": "markdown", - "id": "e32da760-2d7c-44cc-b541-0fd576eaedf2", - "metadata": {}, - "source": [ - "**Answer:**" - ] - }, { "cell_type": "markdown", "id": "9acc19d6-5b85-4ef4-aef4-7cdfe709b566", @@ -1236,14 +1082,6 @@ "No matter what algorithm you choose, **you are encouraged to run small-scale simulations of the problems on quantum backends and simulators, always keeping in mind the resources that you are utilizing and their cost**. What problems/limitations do you encounter in comparison with simulated annealing?" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "bf0bf994", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "dbc17d65-627d-4805-ac9f-3a3803bfc70d", @@ -1270,6 +1108,14 @@ "" ] }, + { + "cell_type": "markdown", + "id": "dcde0919", + "metadata": {}, + "source": [ + "===========================================================================================================================" + ] + }, { "cell_type": "markdown", "id": "990a82c7-6ccc-4552-8b86-97a95fece3cd", @@ -1278,14 +1124,77 @@ "**Answer:**" ] }, + { + "cell_type": "markdown", + "id": "50cd6eb5", + "metadata": {}, + "source": [ + "#### Qiskit Code" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "aa60be68", + "id": "bf0bf994", "metadata": {}, "outputs": [], "source": [ - "# write your code here" + "qubo, _ = model.to_qubo()\n", + "length = (T+number_assets+2)*D+T\n", + "qubo_matrix = np.zeros((length,length))\n", + "for key, value in qubo.items():\n", + " qubo_matrix[key[0],key[1]] = value\n", + " \n", + "from qiskit import BasicAer\n", + "from qiskit_optimization import QuadraticProgram\n", + "from qiskit_optimization.algorithms import MinimumEigenOptimizer\n", + "#from qiskit.aqua import aqua_globals, QuantumInstance\n", + "#from qiskit.aqua.algorithms import QAOA\n", + "\n", + "def solve(Q):\n", + " qp = QuadraticProgram()\n", + " [qp.binary_var() for _ in range(Q.shape[0])]\n", + " qp.minimize(quadratic=Q)\n", + " quantum_instance = QuantumInstance(BasicAer.get_backend('qasm_simulator'))\n", + " qaoa_mes = QAOA(quantum_instance=quantum_instance)\n", + " qaoa = MinimumEigenOptimizer(qaoa_mes)\n", + " qaoa_result = qaoa.solve(qp)\n", + " return [qaoa_result.x], [qaoa_result.fval]" + ] + }, + { + "cell_type": "markdown", + "id": "c266057a", + "metadata": {}, + "source": [ + "#### DWave Code" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "afb3fb92", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " r_e[0] r_e[1] r_e[2] s[0][0] s[0][1] s[0][2] ... y[9] energy num_oc.\n", + "0 0 0 0 0 0 0 ... 1 0.657627 1\n", + "['BINARY', 1 rows, 1 samples, 55 variables]\n" + ] + } + ], + "source": [ + "model = H.compile()\n", + "bqm = model.to_bqm()\n", + "\n", + "from dwave.system import LeapHybridSampler\n", + "import numpy as np\n", + "\n", + "result = LeapHybridSampler().sample(bqm, label='Notebook - Hybrid Computing 1')\n", + "print(result)" ] }, { @@ -1382,7 +1291,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.6" + "version": "3.9.6" }, "vscode": { "interpreter": { From cbd4fa48efaf876344d3c7a844c162404a171284 Mon Sep 17 00:00:00 2001 From: Lakshika Rathi Date: Sun, 4 Feb 2024 09:42:25 -0500 Subject: [PATCH 10/12] final changes --- moodys_challenge.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index b260a32..e2e0816 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -1129,7 +1129,7 @@ "id": "50cd6eb5", "metadata": {}, "source": [ - "#### Qiskit Code" + "#### Qiskit Code: Gate-Based Quantum Simulation" ] }, { @@ -1167,7 +1167,7 @@ "id": "c266057a", "metadata": {}, "source": [ - "#### DWave Code" + "#### DWave Code: Quantum Annealer Based Solution" ] }, { From 811559bbdd1fa1530ef4dff8e3b17fa38c07d973 Mon Sep 17 00:00:00 2001 From: Lakshika Rathi Date: Sun, 4 Feb 2024 09:42:53 -0500 Subject: [PATCH 11/12] final changes --- moodys_challenge.ipynb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index e2e0816..31eec8c 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -655,11 +655,13 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 26, "id": "d84cacd7", "metadata": {}, "outputs": [], "source": [ + "# Encoding of x, slack, r_e\n", + "\n", "def binary_encode(x, D):\n", " bin_x = 0\n", " for d in range(D):\n", @@ -671,7 +673,6 @@ " for d in range(D):\n", " bin_s += (2**d)*s[d]\n", " return bin_s\n", - " #return LogEncInteger(s)\n", "\n", "def encode_r_e(r_e, z, Z):\n", " bin_r = 0\n", @@ -682,11 +683,13 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 27, "id": "a1b3470c", "metadata": {}, "outputs": [], "source": [ + "# Calculation of Hamiltonians\n", + "\n", "def H1(covariance_matrix, x):\n", " ham_1 = 0\n", " n, D = x.shape\n", From 22f6e3d6072a5ac16ba1dd6af02049832162eab0 Mon Sep 17 00:00:00 2001 From: Lakshika Rathi Date: Sun, 4 Feb 2024 09:50:49 -0500 Subject: [PATCH 12/12] final changes --- moodys_challenge.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moodys_challenge.ipynb b/moodys_challenge.ipynb index 31eec8c..0c0d328 100644 --- a/moodys_challenge.ipynb +++ b/moodys_challenge.ipynb @@ -1151,8 +1151,8 @@ "from qiskit import BasicAer\n", "from qiskit_optimization import QuadraticProgram\n", "from qiskit_optimization.algorithms import MinimumEigenOptimizer\n", - "#from qiskit.aqua import aqua_globals, QuantumInstance\n", - "#from qiskit.aqua.algorithms import QAOA\n", + "from qiskit.utils import algorithm_globals, QuantumInstance\n", + "from qiskit.algorithms import QAOA\n", "\n", "def solve(Q):\n", " qp = QuadraticProgram()\n",