diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/.ipynb_checkpoints/QuantumPhaseEstimation-checkpoint.ipynb b/.ipynb_checkpoints/QuantumPhaseEstimation-checkpoint.ipynb new file mode 100644 index 0000000..c2145d1 --- /dev/null +++ b/.ipynb_checkpoints/QuantumPhaseEstimation-checkpoint.ipynb @@ -0,0 +1,241 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile\n", + "from qiskit_aer import AerSimulator\n", + "from qiskit.quantum_info import Operator\n", + "from qiskit.visualization import plot_histogram\n", + "import numpy as np\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "pi=np.pi" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "def qft_rot(circuit, n):\n", + " if n == 0:\n", + " return circuit\n", + " \n", + " n = n-1\n", + " circuit.h(n)\n", + " for i in range(n):\n", + " circuit.cp(pi/(2**(n-i)), i, n)\n", + " \n", + " qft_rot(circuit, n)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "def iqft_rot(circuit, n):\n", + " for i in range(n):\n", + " if i > 0:\n", + " for j in range(i, 0, -1):\n", + " circuit.cp(-pi/(2**j), i, i-j)\n", + " circuit.h(i) \n", + " return circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "def phase_estimation(oracle, eigenstate, number_qubits):\n", + " n = number_qubits\n", + " qr = QuantumRegister(n+1, 'q')\n", + " c = ClassicalRegister(n, 'c')\n", + " qc = QuantumCircuit(qr, c)\n", + " \n", + " if eigenstate == 1:\n", + " qc.x(n)\n", + " \n", + " for i in range(n//2):\n", + " qc.swap(i, n-i-1)\n", + " \n", + " for i in range(3):\n", + " qc.h(i) \n", + " \n", + " cGate = oracle.control(1)\n", + " qc.barrier()\n", + " \n", + " for i in range(n):\n", + " for j in range(2**i):\n", + " qc.append(cGate, [i, n])\n", + " \n", + " qc.barrier()\n", + " iqft_rot(qc, n+1)\n", + " qc.barrier()\n", + " \n", + " for i in range(n):\n", + " qc.measure(i, i)\n", + " \n", + " aersim = AerSimulator(shots=1000)\n", + " circuit_transpile = transpile(qc, aersim)\n", + " result = aersim.run(circuit_transpile).result()\n", + " counts = result.get_counts()\n", + " \n", + " # Get the most common bitstring and convert to phase\n", + " most_common_bitstring = max(counts, key=counts.get)\n", + " N = len(most_common_bitstring)\n", + " phase = int(most_common_bitstring, 2) / 2**N\n", + " \n", + " hist = plot_histogram(counts, title=f\"Phase Estimation for |{1}>\")\n", + " \n", + " return counts, phase, qc" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "def create_gate_from_matrix(matrix):\n", + " \"\"\"\n", + " Create a quantum circuit from a nxn unitary matrix\n", + " \"\"\"\n", + " n = matrix.shape[0]\n", + " n_qubits = int(math.log2(n))\n", + " qc = QuantumCircuit(1) # We only need 1 qubit for 2x2 matrix\n", + " \n", + " op = Operator(matrix)\n", + " qc.unitary(op, [0], label='L')\n", + " \n", + " return qc" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "def analyze_phases(counts, n_qubits, zero_threshold=1e-3):\n", + " \"\"\"\n", + " Analyze phases from measurement results and count zero phases\n", + " \"\"\"\n", + " total_shots = sum(counts.values())\n", + " phases = {}\n", + " zero_phase_count = 0\n", + " \n", + " for bitstring, count in counts.items():\n", + " phase = int(bitstring, 2) / (2**n_qubits)\n", + " probability = count / total_shots\n", + " phases[phase] = probability\n", + " \n", + " if phase < zero_threshold:\n", + " zero_phase_count += 1\n", + " \n", + " return phases, zero_phase_count" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "def analyze_matrix(matrix, n_qubits=4, zero_threshold=1e-3):\n", + " \"\"\"\n", + " Analyze a matrix using QPE to detect zero eigenvalues\n", + " \"\"\"\n", + " \n", + " # Create gate from matrix\n", + " gate = create_gate_from_matrix(matrix)\n", + " \n", + " # Run phase estimation\n", + " counts, estimated_phase, _ = phase_estimation(gate, 1, n_qubits)\n", + " \n", + " # Analyze phases and count zeros\n", + " phases, zero_count = analyze_phases(counts, n_qubits, zero_threshold)\n", + " \n", + " print(f\"\\nResults:\")\n", + " print(f\"Estimated primary phase: {estimated_phase:.4f}\")\n", + " print(f\"Number of zero phases detected: {zero_count}\")\n", + " \n", + " return zero_count" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Analyzing matrix:\n", + "[[0.99500417-0.09983342j 0. +0.j ]\n", + " [0. +0.j 0.99500417-0.09983342j]]\n", + "\n", + "Results:\n", + "Estimated primary phase: 0.0000\n", + "Number of zero phases detected: 1\n", + "\n", + "Final result: 1 zero eigenvalues detected\n" + ] + } + ], + "source": [ + "L = np.array([[0.99500417-0.09983342j, 0],\n", + " [0, 0.99500417-0.09983342j]])\n", + "\n", + "print(\"Analyzing matrix:\")\n", + "print(L)\n", + "n_zeros = analyze_matrix(L)\n", + "print(f\"\\nFinal result: {n_zeros} zero eigenvalues detected\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "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.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/README-checkpoint.md b/.ipynb_checkpoints/README-checkpoint.md new file mode 100644 index 0000000..3070f5c --- /dev/null +++ b/.ipynb_checkpoints/README-checkpoint.md @@ -0,0 +1,70 @@ +# iQuHACK 2025 - Moody's Challenge + +Here you will learn the details that are needed in order to access and operate resources for this challenge. See **moodys_challenge** to read the challenge. Make sure to first read the instructions below. + +## Working on qBraid +[](https://account.qbraid.com?gitHubUrl=https://github.com/iQuHACK/2025-Moodys.git) + +While simulations and emulations of your program can be done locally on your computer, the Moody's challenge will require access to qBraid for quantum hardware. + +So here are some guidelines: +1. To launch these materials on qBraid, first fork this repository and click the above `Launch on qBraid` button. It will take you to your qBraid Lab with the repository cloned. +2. Once cloned, open terminal (click **FILES** in the left sidebar, then click the blue button with a symbol "➕", it is the first icon in the **Other** column in Launcher) and `cd` into this repo. Set the repo's remote origin using the git clone url you copied in Step 1, and then create a new branch for your team: + +```bash +cd 2025-Moodys +git remote set-url origin +git branch +git checkout + +``` + +3. Use the environment manager (**ENVS** tab in the right sidebar) to [install environment](https://docs.qbraid.com/cli/user-guide/environments) "Moody's IQuHACK 2025". The installation should take ~2 min. +4. Once the installation is complete, go back to the Launcher to [add a new ipykernel](https://docs.qbraid.com/lab/user-guide/kernels) for "Moody's". +5. From the **FILES** tab in the left sidebar, double-click on the `2024_Moodys` directory. +6. You are now ready to begin hacking, [submitting jobs](https://docs.qbraid.com/lab/user-guide/quantum-jobs)! Work with your team to complete the challenge listed above. + +Please note, you will be provisioned credits before the hackathon for quantum hardwares. The following resources are provided in this challenge: + +* IonQ Aria 1 Noisy Quantum Simulator (no time limit, [qiskit syntax](#Syntax-of-using-IonQ-simulator-on-qiskit-circuit), [other syntax](https://docs.qbraid.com/sdk/user-guide/providers/ionq)) +* IBM hardware (10 minutes, [syntax](https://docs.qbraid.com/sdk/user-guide/providers/ibm)) + +**Strategize carefully and conduct back of the envelope estimates for your experiments before running**. + +For other questions or additional help using qBraid, see [Lab User Guide](https://docs.qbraid.com/projects/lab/en/latest/lab/overview.html), or reach out on the IQuHack qBraid Slack Channel. + +## Before submission + +Make sure that you devote some time to prepare a brief presentation (3-7 mins) showing your work. This presentation will be presented on Sunday. + +We encourage you to show your experimental results, and your innovative solutions. + +## Syntax of using IonQ simulator on qiskit circuit + +Qiskit circuit is used as an example here. + +```python +from qbraid.programs import load_program +from qbraid.runtime import QbraidProvider +from qbraid.transpiler.conversions.qiskit import qiskit_to_ionq + +provider = QbraidProvider() + +device = provider.get_device("ionq_simulator") + +ionq_dict = qiskit_to_ionq(circuit, gateset="native") + +program = load_program(ionq_dict) + +run_input = program.serialize() + +job = device.submit(run_input, shots=100, noise_model="aria-1") +``` + +## Scoring Criteria + +The scoring criteria are as follows: + +- **55%** is based on the main quantum TDA workflow (steps 1~4). +- **40%** is allocated to creativity and innovation, evaluated through the work on one of challenge from the BONUS section. +- **5%** is assigned to presentation quality. diff --git a/.ipynb_checkpoints/betti_analysis-checkpoint.svg b/.ipynb_checkpoints/betti_analysis-checkpoint.svg new file mode 100644 index 0000000..496917b --- /dev/null +++ b/.ipynb_checkpoints/betti_analysis-checkpoint.svg @@ -0,0 +1,25307 @@ + + + + + + + + 2025-02-01T19:06:50.585799 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moodys_challenge.ipynb b/.ipynb_checkpoints/moodys_challenge-checkpoint.ipynb similarity index 79% rename from moodys_challenge.ipynb rename to .ipynb_checkpoints/moodys_challenge-checkpoint.ipynb index 7ee0e87..28d9655 100644 --- a/moodys_challenge.ipynb +++ b/.ipynb_checkpoints/moodys_challenge-checkpoint.ipynb @@ -161,15 +161,134 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "4ec880cd", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01
003/01/20001460.200
104/01/20001426.800
205/01/20001398.125
306/01/20001402.375
407/01/20001421.750
.........
553127/12/20214762.675
553228/12/20214792.225
553329/12/20214790.975
553430/12/20214789.275
553531/12/20214773.500
\n", + "

5536 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " 0 1\n", + "0 03/01/2000 1460.200\n", + "1 04/01/2000 1426.800\n", + "2 05/01/2000 1398.125\n", + "3 06/01/2000 1402.375\n", + "4 07/01/2000 1421.750\n", + "... ... ...\n", + "5531 27/12/2021 4762.675\n", + "5532 28/12/2021 4792.225\n", + "5533 29/12/2021 4790.975\n", + "5534 30/12/2021 4789.275\n", + "5535 31/12/2021 4773.500\n", + "\n", + "[5536 rows x 2 columns]" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import pandas as pd\n", "import numpy as np\n", "\n", - "time_series = np.log(pd.read_csv(\"SP500.csv\", header=None).to_numpy().squeeze())" + "df = pd.read_csv(\"sp500_full.csv\", header=None)\n", + "df\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "240232aa-4a72-496c-8ab3-30f6a2aacc5b", + "metadata": {}, + "outputs": [], + "source": [ + "time_series = np.log(df[1]).to_numpy().squeeze()" ] }, { @@ -209,12 +328,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 122, "id": "7b701be6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 3, w = 10, L = 5536\n" + ] + } + ], "source": [ - "# write your code here" + "N = 3 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 10 # window size\n", + "\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "Z = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n" ] }, { @@ -273,12 +409,52 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 125, "id": "026d6b61", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num 0-simplices: 10\n", + "num 1-simplices: 0\n", + "num 2-simplices: 0\n" + ] + } + ], "source": [ - "# write your code here" + "import gudhi\n", + "\n", + "epsilon = 0.001 # maximum edge length\n", + "max_dim = 2 # maximum simplex dimension\n", + "\n", + "all_simplices = []\n", + "\n", + "point_cloud = Z[0]\n", + "\n", + "\n", + " \n", + "def get_simplex_tree(point_cloud, epsilon):\n", + " # Simplicial Complex\n", + " rips = gudhi.RipsComplex(points=point_cloud, max_edge_length=epsilon)\n", + " filtration = rips.create_simplex_tree(max_dimension=max_dim).get_filtration()\n", + "\n", + " # Extract simplices by dimension\n", + " simplex_tree = [[] for _ in range(max_dim + 1)]\n", + " for simplex, filtration_value in filtration:\n", + " if filtration_value <= epsilon:\n", + " dim = len(simplex) - 1\n", + " simplex_tree[dim].append(simplex)\n", + " return simplex_tree\n", + "\n", + "simplex_tree = get_simplex_tree(point_cloud, epsilon)\n", + "\n", + "print(f\"num 0-simplices: {len(simplex_tree[0])}\")\n", + "print(f\"num 1-simplices: {len(simplex_tree[1])}\")\n", + "print(f\"num 2-simplices: {len(simplex_tree[2])}\")\n", + "# for dim, simplices in enumerate(simplex_tree):\n", + "# print(f\"{dim}-simplices: {simplices}\")" ] }, { @@ -337,12 +513,57 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "246e41ce", + "execution_count": 98, + "id": "c9a4b17b-188b-4f47-9739-9434451b8e0c", "metadata": {}, "outputs": [], "source": [ - "# write your code here" + "simplex_tree = [[[1],[2],[3],[4],[5]],[[1,2],[1,3],[2,3],[3,4],[3,5],[4,5]],[[1,2,3]]]" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "id": "246e41ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Boundary 1: (10, 0)\n", + "[]\n", + "Boundary 2: (0, 0)\n", + "[]\n" + ] + } + ], + "source": [ + "def boundary(k, simplex_tree): # geenrates boundary operator C_{k} -> C_{k-1}\n", + " if k == 0:\n", + " return None \n", + " \n", + " sk = simplex_tree[k] # k-simplices\n", + " sk_1 = simplex_tree[k-1] # (k-1)-simplices\n", + " \n", + " boundary = np.zeros((len(sk_1), len(sk)), dtype=int)\n", + " \n", + " for j, simplex in enumerate(sk):\n", + " for i in range(k+1):\n", + " face = simplex[:i] + simplex[i+1:]\n", + " index = sk_1.index(list(face))\n", + " boundary[index, j] = (-1)**i\n", + " \n", + " return boundary\n", + "\n", + "boundary1 = boundary(1, simplex_tree)\n", + "boundary2 = boundary(2, simplex_tree)\n", + "\n", + "print(\"Boundary 1:\", boundary1.shape)\n", + "print(boundary1)\n", + "\n", + "print(\"Boundary 2:\", boundary2.shape)\n", + "print(boundary2)" ] }, { @@ -423,14 +644,119 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "8f818f78", + "execution_count": 127, + "id": "dbf2431a-aa85-41e1-a72c-563afec9c949", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + ":10: RuntimeWarning: divide by zero encountered in log2\n", + " q = int(np.ceil(np.log2(n)))\n" + ] + }, + { + "ename": "OverflowError", + "evalue": "cannot convert float infinity to integer", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mOverflowError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 34\u001b[0m \u001b[0mk\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 35\u001b[0;31m \u001b[0mlaplacian\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_laplacian\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msimplex_tree\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 36\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Laplacian:\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlaplacian\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 37\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlaplacian\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mget_laplacian\u001b[0;34m(k, simplex_tree)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;31m# padding\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mn\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlaplacian\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mq\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mceil\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlog2\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0mn_pad\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mq\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mn\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0mlambda_max\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmax_eigenvalue\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlaplacian\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mOverflowError\u001b[0m: cannot convert float infinity to integer" + ] + } + ], "source": [ - "# write your code here" + "from scipy.linalg import expm\n", + "\n", + "def get_laplacian(k, simplex_tree): # Get combinatorial laplaian\n", + " boundary_k = boundary(k, simplex_tree) # boundary k\n", + " boundary_k1 = boundary(k+1, simplex_tree) # boundary k+1\n", + " laplacian = boundary_k.T @ boundary_k + boundary_k1 @ boundary_k1.T\n", + " \n", + " # padding\n", + " n = laplacian.shape[0]\n", + " q = int(np.ceil(np.log2(n)))\n", + " n_pad = 2**q - n\n", + " lambda_max = max_eigenvalue(laplacian)\n", + " \n", + " padded_laplacian = np.zeros((2**q, 2**q))\n", + " padded_laplacian[:n, :n] = laplacian\n", + " padded_laplacian[n:, n:] = np.eye(n_pad) * (lambda_max/2)\n", + " \n", + " return padded_laplacian\n", + "\n", + "def max_eigenvalue(matrix): # estimate max eigenvalue using Gershgorin circle theorem\n", + " row_sums = np.sum(np.abs(matrix), axis=1)\n", + " return np.max(row_sums)\n", + "\n", + "\n", + "\n", + "def get_unitary(laplacian):\n", + " delta = 2 * np.pi - 0.1 # can change tolerance = 0.1\n", + " lambda_max = max_eigenvalue(laplacian)\n", + " \n", + " H = delta / lambda_max * laplacian\n", + " U = expm(1j * H)\n", + " return U\n", + "\n", + "k = 1\n", + "laplacian = get_laplacian(k, simplex_tree)\n", + "print(\"Laplacian:\", laplacian.shape)\n", + "print(laplacian)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "099d53c4-e199-4456-8f73-4dd9808b6f0d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Unitary: (64, 64)\n", + "[[ 0.99500417-0.09983342j 0. +0.j 0. +0.j\n", + " ... 0. +0.j 0. +0.j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0.99500417-0.09983342j 0. +0.j\n", + " ... 0. +0.j 0. +0.j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0.99500417-0.09983342j\n", + " ... 0. +0.j 0. +0.j\n", + " 0. +0.j ]\n", + " ...\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " ... -0.99875026+0.04997917j 0. +0.j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " ... 0. +0.j -0.99875026+0.04997917j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " ... 0. +0.j 0. +0.j\n", + " -0.99875026+0.04997917j]]\n" + ] + } + ], + "source": [ + "\n", + "U = get_unitary(laplacian)\n", + "print(\"Unitary:\", U.shape)\n", + "print(U)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "73f45de9-8671-45dd-84ff-0544a86b982d", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "0acfea73", @@ -460,6 +786,14 @@ "Where $\\tilde{\\beta}_k$ is the estimation of $k$-th Betti number. This estimation is then rounded to the nearest integer to obtain the final result." ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5db566e-4e93-47f6-816a-b093536b081f", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "fc95fe90", @@ -497,6 +831,27 @@ "**Answer:**" ] }, + { + "cell_type": "code", + "execution_count": 37, + "id": "1f7cacde-92e8-4caf-8e41-1de22834a5f6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(64, 64)" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "U.shape" + ] + }, { "cell_type": "code", "execution_count": null, @@ -504,7 +859,160 @@ "metadata": {}, "outputs": [], "source": [ - "# write your code here" + "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile\n", + "from qiskit_aer import AerSimulator\n", + "from qiskit.quantum_info import Operator\n", + "from qiskit.visualization import plot_histogram\n", + "import numpy as np\n", + "import math\n", + "\n", + "pi=np.pi\n", + "def qft_rot(circuit, n):\n", + " if n == 0:\n", + " return circuit\n", + " \n", + " n = n-1\n", + " circuit.h(n)\n", + " for i in range(n):\n", + " circuit.cp(pi/(2**(n-i)), i, n)\n", + " \n", + " qft_rot(circuit, n)\n", + " \n", + "def iqft_rot(circuit, n):\n", + " for i in range(n):\n", + " if i > 0:\n", + " for j in range(i, 0, -1):\n", + " circuit.cp(-pi/(2**j), i, i-j)\n", + " circuit.h(i) \n", + " return circuit\n", + "\n", + "def phase_estimation(oracle, eigenstate, number_qubits):\n", + " n = number_qubits\n", + " \n", + " # Calculate number of target qubits needed from oracle size\n", + " oracle_size = oracle.num_qubits # Get directly from circuit\n", + " \n", + " # Create registers: n counting qubits + oracle_size target qubits\n", + " qr = QuantumRegister(n + oracle_size, 'q')\n", + " c = ClassicalRegister(n, 'c')\n", + " qc = QuantumCircuit(qr, c)\n", + "\n", + " # Initialize eigenstate\n", + " if eigenstate == 1:\n", + " for i in range(oracle_size):\n", + " qc.x(n + i) # Initialize target qubits\n", + "\n", + " # Swap order of counting qubits if needed\n", + " for i in range(n//2):\n", + " qc.swap(i, n-i-1)\n", + "\n", + " # Apply Hadamard to all counting qubits\n", + " for i in range(n):\n", + " qc.h(i)\n", + "\n", + " # Create controlled version of oracle\n", + " cGate = oracle.control(1)\n", + " qc.barrier()\n", + "\n", + " # Apply controlled operations with proper target qubits\n", + " for i in range(n):\n", + " for j in range(2**i):\n", + " # Get number of qubits needed for controlled operation\n", + " n_control = cGate.num_qubits - oracle_size # Number of control qubits\n", + " # Create list of target qubits that matches controlled operation's expectation\n", + " all_qubits = [i] + list(range(n, n + oracle_size))\n", + " qc.append(cGate, all_qubits)\n", + "\n", + " qc.barrier()\n", + " iqft_rot(qc, n+1)\n", + " qc.barrier()\n", + "\n", + " # Measure counting qubits\n", + " for i in range(n):\n", + " qc.measure(i, i)\n", + "\n", + " aersim = AerSimulator(shots=1000)\n", + " circuit_transpile = transpile(qc, aersim)\n", + " result = aersim.run(circuit_transpile).result()\n", + " counts = result.get_counts()\n", + " \n", + " most_common_bitstring = max(counts, key=counts.get)\n", + " N = len(most_common_bitstring)\n", + " phase = int(most_common_bitstring, 2) / 2**N\n", + " \n", + " return counts, phase, qc\n", + "\n", + "def create_gate_from_matrix(matrix):\n", + " \"\"\"\n", + " Create a quantum circuit from a nxn unitary matrix\n", + " \"\"\"\n", + " n = matrix.shape[0]\n", + " n_qubits = int(math.log2(n)) # Calculate number of qubits needed\n", + " # print(f\"Matrix size: {n}x{n}\")\n", + " # print(f\"Number of qubits needed: {n_qubits}\")\n", + " \n", + " # Create circuit with the correct number of qubits\n", + " qc = QuantumCircuit(n_qubits)\n", + " \n", + " # Create list of qubits to apply unitary to\n", + " qubits = list(range(n_qubits))\n", + " # print(f\"Applying unitary to qubits: {qubits}\")\n", + " \n", + " # Create operator and verify its dimension\n", + " op = Operator(matrix)\n", + " # print(f\"Operator dimension: {op.dim}\")\n", + " \n", + " # Apply the unitary\n", + " qc.unitary(op, qubits, label='L')\n", + " \n", + " return qc\n", + "\n", + "def analyze_phases(counts, n_qubits, zero_threshold=1e-3):\n", + " \"\"\"\n", + " Analyze phases from measurement results and count zero phases\n", + " \"\"\"\n", + " total_shots = sum(counts.values())\n", + " phases = {}\n", + " zero_phase_count = 0\n", + " \n", + " for bitstring, count in counts.items():\n", + " phase = int(bitstring, 2) / (2**n_qubits)\n", + " probability = count / total_shots\n", + " phases[phase] = probability\n", + " \n", + " if phase < zero_threshold:\n", + " zero_phase_count += 1\n", + " \n", + " return phases, zero_phase_count\n", + "\n", + "\n", + "def analyze_matrix(matrix, n_qubits=4, zero_threshold=1e-3):\n", + " \"\"\"\n", + " Analyze a matrix using QPE to detect zero eigenvalues\n", + " \"\"\"\n", + " \n", + " # Create gate from matrix\n", + " gate = create_gate_from_matrix(matrix)\n", + " \n", + " # Run phase estimation\n", + " counts, estimated_phase, qc = phase_estimation(gate, 1, n_qubits)\n", + " \n", + " # Analyze phases and count zeros\n", + " phases, zero_count = analyze_phases(counts, n_qubits, zero_threshold)\n", + " \n", + " # print(f\"\\nResults:\")\n", + " # print(f\"Estimated primary phase: {estimated_phase:.4f}\")\n", + " # print(f\"Number of zero phases detected: {zero_count}\")\n", + " \n", + " return zero_count,qc\n", + "\n", + "L = np.array([[0.99500417-0.09983342j, 0],\n", + " [0, 0.99500417-0.09983342j]])\n", + "\n", + "print(\"Analyzing matrix:\")\n", + "print(L)\n", + "n_zeros = analyze_matrix(U)\n", + "print(f\"\\nFinal result: {n_zeros} zero eigenvalues detected\")" ] }, { @@ -560,10 +1068,153 @@ }, { "cell_type": "code", - "execution_count": 2, - "id": "5ef68f98", + "execution_count": 149, + "id": "700a1375-a1b5-4424-bd1d-0b2b2b7e28d5", "metadata": {}, "outputs": [], + "source": [ + "def get_betti_number(point_cloud, epsilon, dim):\n", + " # print(\"Constructing tree\")\n", + " simplex_tree = get_simplex_tree(point_cloud, epsilon)\n", + " # print(f\"num 0-simplices: {len(simplex_tree[0])}\")\n", + " # print(f\"num 1-simplices: {len(simplex_tree[1])}\")\n", + " # print(f\"num 2-simplices: {len(simplex_tree[2])}\")\n", + " if len(simplex_tree[dim]) == 0:\n", + " return 0\n", + " # print(\"Computing laplacian\")\n", + " laplacian = get_laplacian(dim, simplex_tree)\n", + " if laplacian.shape[0] ==1:\n", + " return 1 if abs(laplacian[0][0]) < 1e-9 else 0\n", + " # print(f\"Laplacian: {laplacian.shape}\")\n", + " # print(laplacian)\n", + " # print(\"Computing unitary\")\n", + " unitary = get_unitary(laplacian)\n", + " # print(f\"Unitary: {unitary.shape}\")\n", + " print(unitary)\n", + " # print(\"Performing QPE\")\n", + " betti_number = analyze_matrix(unitary)[0]\n", + " return betti_number" + ] + }, + { + "cell_type": "code", + "execution_count": 132, + "id": "c9be7d6a-b072-41ee-aaf9-77cada9c5394", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[7.28632869, 7.26318945, 7.24288733],\n", + " [7.26318945, 7.24288733, 7.24592251],\n", + " [7.24288733, 7.24592251, 7.25964379],\n", + " [7.24592251, 7.25964379, 7.28018053],\n", + " [7.25964379, 7.28018053, 7.27748958],\n", + " [7.28018053, 7.27748958, 7.26959934],\n", + " [7.27748958, 7.26959934, 7.27390767],\n", + " [7.26959934, 7.27390767, 7.28578067],\n", + " [7.27390767, 7.28578067, 7.28562649],\n", + " [7.28578067, 7.28562649, 7.28308759]])" + ] + }, + "execution_count": 132, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "point_cloud" + ] + }, + { + "cell_type": "code", + "execution_count": 133, + "id": "5c9c3614-a31d-4d0b-8142-da52d2ad0f51", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Constructing tree\n", + "num 0-simplices: 10\n", + "num 1-simplices: 45\n", + "num 2-simplices: 120\n", + "Computing laplacian\n", + "Laplacian: (64, 64)\n", + "[[10. 0. 0. ... 0. 0. 0.]\n", + " [ 0. 10. 0. ... 0. 0. 0.]\n", + " [ 0. 0. 10. ... 0. 0. 0.]\n", + " ...\n", + " [ 0. 0. 0. ... 5. 0. 0.]\n", + " [ 0. 0. 0. ... 0. 5. 0.]\n", + " [ 0. 0. 0. ... 0. 0. 5.]]\n", + "Computing unitary\n", + "Unitary: (64, 64)\n", + "[[ 0.99500417-0.09983342j 0. +0.j 0. +0.j\n", + " ... 0. +0.j 0. +0.j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0.99500417-0.09983342j 0. +0.j\n", + " ... 0. +0.j 0. +0.j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0.99500417-0.09983342j\n", + " ... 0. +0.j 0. +0.j\n", + " 0. +0.j ]\n", + " ...\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " ... -0.99875026+0.04997917j 0. +0.j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " ... 0. +0.j -0.99875026+0.04997917j\n", + " 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " ... 0. +0.j 0. +0.j\n", + " -0.99875026+0.04997917j]]\n", + "Performing QPE\n", + "Matrix size: 64x64\n", + "Number of qubits needed: 6\n", + "Applying unitary to qubits: [0, 1, 2, 3, 4, 5]\n", + "Operator dimension: (64, 64)\n", + "\n", + "Results:\n", + "Estimated primary phase: 0.9375\n", + "Number of zero phases detected: 0\n" + ] + }, + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 133, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "epsilon = 0.1\n", + "dim = 1\n", + "get_betti_number(point_cloud, epsilon, dim)" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "id": "5ef68f98", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 144, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "from ripser import ripser\n", "\n", @@ -580,9 +1231,1369 @@ " [interval for interval in diagrams[dim] if interval[0] < epsilon < interval[1]]\n", " )\n", "\n", + "classical_betti_solver(point_cloud, epsilon, dim)\n", "# write your code here" ] }, + { + "cell_type": "code", + "execution_count": 57, + "id": "167f3f1b-4951-4a78-ac2f-ec5b299f5bb9", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 150, + "id": "10d09048-6a55-46f5-b1be-30f782e62f80", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 3, w = 10, L = 5536\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Calculating Betti numbers: 100%|██████████| 300/300 [00:00<00:00, 1590.97it/s]\n" + ] + }, + { + "data": { + "image/png": "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eecxY8aMhtUwSaJF8SbL4no48puNp59ebi2SJI3qXe+C22+v73uuXg1XXDHiU/r7+4kILr/8cjZs2MC6detoayu2B2XHaxiTZXE9wJlnZteu85IkaXTr16/nscceY+vWrVx99dV86EMfYteuXcM+f8eOHXz84x+vy7EnSbQo3mSaapw1C045xeAlSZokRulMFWH+/PlcdNFF3HjjjUybNo2FCxcO+9zFixc/MzU5UXa8hjGZFtdDts7LvbwkSRrZww8/zD333APAzTffzKmnnnrEOq/hzJw5k/3790/4+AavYUymjhdk67zuuQcOHy67EkmSmteUKVO48MILWbVqFY888ghvf/vb2bt37zOPL126lHe/+9380z/9E0uWLOHOO+8E4ODBg8yePXvix5/wO7Soydbx6urKtpO4+254wQvKrkaSpOa0ePHi55woe/HixezatYuFCxeydevW57xmx44drFixoi7Ht+M1jMnY8QLXeUmSdLQuvfTSUdd4/f7v/35djmXwGsZk2k4CYPnyLCgavCRJqu3kk09+TreraAavYUym7SQApk2DFStcYC9JUjMzeA1jsk01gudslCSp2Rm8hjHZFtdDFry2boV9+8quRJIk1WLwGsZk7XhBdsJsSZLUfAxew5iMHa9Vq7Jr13lJklTblVdeyfLly1m5ciXr168/4rHrrruOc845h1WrVnHOOefw7W9/u+7Hn2Q9neJMxo7X0qVwzDGu85IkqZbDhw9z2WWXce+999LR0cFJJ53EJZdcwrHHHgvAwoULufbaaznhhBPYtGkTF1xwAdu3b69rDZMsWhRnsm0nAdDWBitXGrwkSapl586dHH/88cyfP5/NmzcDHHG6oLPOOuuZ2ytXruTgwYMcPnyY6dOn160Gg9cwJtt2EgO6uuCrXy27CkmShveur7+L2396e13fc/Xxq7nil64Y8Tn9/f1EBJdffjkbNmxg3bp1tLXVXnX1hS98gbPPPruuoQsMXsOajFONkK3z+sd/hDe9CdrbR37u1Knw3vfCqacWU5skSc1g/fr1vO1tb+NNb3oTV199NY8//jhvfetbn9m9fvPmzVx66aV885vfBLJTBn3xi1+sy+71kzBaFGMyLq4HuOACeP7z4cYbR35eStnWE2ecAZdcUkhpkiQBjNqZKsL8+fO56KKLuPHGG5k2bdozoWvbtm28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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Maximum β₍0₎: 10\n", + "Maximum β₍1₎: 1\n", + "Maximum β₍2₎: 0\n" + ] + } + ], + "source": [ + "from tqdm import tqdm\n", + "\n", + "N = 3 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 10 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "\n", + "# Define ranges\n", + "eps_range = np.linspace(0, 0.1, 100)\n", + "k_range = [0,1,2] # Calculate for k = 0, 1, and 2\n", + "\n", + "# Dictionary to store Betti numbers for each k\n", + "betti_numbers = {k: [] for k in k_range}\n", + "\n", + "# Calculate Betti numbers for each epsilon and k with progress bar\n", + "total_iterations = len(eps_range) * len(k_range)\n", + "with tqdm(total=total_iterations, desc=\"Calculating Betti numbers\") as pbar:\n", + " for eps in eps_range:\n", + " for k in k_range:\n", + " betti_numbers[k].append(classical_betti_solver(point_cloud, eps, k))\n", + " pbar.update(1)\n", + "\n", + "# Create plot\n", + "plt.figure(figsize=(10, 6))\n", + "colors = ['blue', 'red', 'green'] # One color for each k\n", + "\n", + "# Plot each k dimension\n", + "for k, color in zip(k_range, colors):\n", + " plt.plot(eps_range, betti_numbers[k], \n", + " color=color, \n", + " label=f'β₍{k}₎')\n", + "\n", + "plt.xlabel('ε (Epsilon)')\n", + "plt.ylabel('Betti Number')\n", + "plt.title('Betti Curves')\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "# Print maximum values\n", + "for k in k_range:\n", + " print(f\"Maximum β₍{k}₎: {max(betti_numbers[k])}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f17199a1-9377-4585-8e75-a812017a9843", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 3, w = 10, L = 5536\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Calculating Betti numbers: 0%| | 0/100 [00:00 \u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/scipy/linalg/_decomp_cossin.py\u001b[0m(131)\u001b[0;36mcossin\u001b[0;34m()\u001b[0m\n", + "\u001b[0;32m 129 \u001b[0;31m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m 130 \u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mX\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\u001b[0;32m--> 131 \u001b[0;31m raise ValueError(\"When p and q are None, exactly four arrays\"\n", + "\u001b[0m\u001b[0;32m 132 \u001b[0;31m \" should be in X, got {}\".format(len(X)))\n", + "\u001b[0m\u001b[0;32m 133 \u001b[0;31m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0m\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "ipdb> unitary\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "*** NameError: name 'unitary' is not defined\n" + ] + }, + { + "name": "stdin", + "output_type": "stream", + "text": [ + "ipdb> return\n" + ] + } + ], + "source": [ + "%debug" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "id": "c03b5686-6942-4bdc-87d5-ecd3ceebc550", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01
003/01/20001460.200
104/01/20001426.800
205/01/20001398.125
306/01/20001402.375
407/01/20001421.750
.........
553127/12/20214762.675
553228/12/20214792.225
553329/12/20214790.975
553430/12/20214789.275
553531/12/20214773.500
\n", + "

5536 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " 0 1\n", + "0 03/01/2000 1460.200\n", + "1 04/01/2000 1426.800\n", + "2 05/01/2000 1398.125\n", + "3 06/01/2000 1402.375\n", + "4 07/01/2000 1421.750\n", + "... ... ...\n", + "5531 27/12/2021 4762.675\n", + "5532 28/12/2021 4792.225\n", + "5533 29/12/2021 4790.975\n", + "5534 30/12/2021 4789.275\n", + "5535 31/12/2021 4773.500\n", + "\n", + "[5536 rows x 2 columns]" + ] + }, + "execution_count": 100, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "id": "45a95b97-9dc7-4581-8278-e82613717c73", + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "Multi-dimensional indexing (e.g. `obj[:, None]`) is no longer supported. Convert to a numpy array before indexing instead.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;31m# Create the plot\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfigure\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfigsize\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m12\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m6\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0msns\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlineplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;31m# Customize the plot\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/seaborn/relational.py\u001b[0m in \u001b[0;36mlineplot\u001b[0;34m(data, x, y, hue, size, style, units, weights, palette, hue_order, hue_norm, sizes, size_order, size_norm, dashes, markers, style_order, estimator, errorbar, n_boot, seed, orient, sort, err_style, err_kws, legend, ci, ax, **kwargs)\u001b[0m\n\u001b[1;32m 513\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"color\"\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_default_color\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mhue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcolor\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 514\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 515\u001b[0;31m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0max\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 516\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 517\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/seaborn/relational.py\u001b[0m in \u001b[0;36mplot\u001b[0;34m(self, ax, kws)\u001b[0m\n\u001b[1;32m 314\u001b[0m \u001b[0mlines\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0munit_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"x\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munit_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"y\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkws\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 315\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 316\u001b[0;31m \u001b[0mlines\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msub_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"x\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msub_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"y\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkws\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 317\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 318\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mline\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlines\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/matplotlib/axes/_axes.py\u001b[0m in \u001b[0;36mplot\u001b[0;34m(self, scalex, scaley, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 1603\u001b[0m \"\"\"\n\u001b[1;32m 1604\u001b[0m \u001b[0mkwargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcbook\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnormalize_kwargs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmlines\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mLine2D\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1605\u001b[0;31m \u001b[0mlines\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_lines\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1606\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mline\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mlines\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1607\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_line\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/matplotlib/axes/_base.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, data, *args, **kwargs)\u001b[0m\n\u001b[1;32m 313\u001b[0m \u001b[0mthis\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 314\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 315\u001b[0;31m \u001b[0;32myield\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_plot_args\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mthis\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 316\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 317\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mget_next_color\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/matplotlib/axes/_base.py\u001b[0m in \u001b[0;36m_plot_args\u001b[0;34m(self, tup, kwargs, return_kwargs)\u001b[0m\n\u001b[1;32m 488\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 489\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxy\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 490\u001b[0;31m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_check_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxy\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 491\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_check_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mxy\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 492\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/Library/Python/3.9/lib/python/site-packages/matplotlib/cbook/__init__.py\u001b[0m in \u001b[0;36m_check_1d\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 1360\u001b[0m message='Support for multi-dimensional indexing')\n\u001b[1;32m 1361\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1362\u001b[0;31m \u001b[0mndim\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1363\u001b[0m \u001b[0;31m# we have definitely hit a pandas index or series object\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1364\u001b[0m \u001b[0;31m# cast to a numpy array.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/series.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 1151\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_rows_with_mask\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1152\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1153\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_with\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1154\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1155\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_get_with\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/series.py\u001b[0m in \u001b[0;36m_get_with\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 1161\u001b[0m )\n\u001b[1;32m 1162\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1163\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_values_tuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1164\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1165\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mis_list_like\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/series.py\u001b[0m in \u001b[0;36m_get_values_tuple\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 1201\u001b[0m \u001b[0;31m# the asarray is needed to avoid returning a 2D DatetimeArray\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1202\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0masarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_values\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1203\u001b[0;31m \u001b[0mdisallow_ndim_indexing\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1204\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1205\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/pandas/core/indexers/utils.py\u001b[0m in \u001b[0;36mdisallow_ndim_indexing\u001b[0;34m(result)\u001b[0m\n\u001b[1;32m 339\u001b[0m \"\"\"\n\u001b[1;32m 340\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndim\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 341\u001b[0;31m raise ValueError(\n\u001b[0m\u001b[1;32m 342\u001b[0m \u001b[0;34m\"Multi-dimensional indexing (e.g. `obj[:, None]`) is no longer \"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 343\u001b[0m \u001b[0;34m\"supported. Convert to a numpy array before indexing instead.\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: Multi-dimensional indexing (e.g. `obj[:, None]`) is no longer supported. Convert to a numpy array before indexing instead." + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "df[0] = pd.to_datetime(df[0], format = \"%d/%m/%Y\")\n", + "\n", + "# Create the plot\n", + "plt.figure(figsize=(12, 6))\n", + "sns.lineplot(data=df, x=0, y=1)\n", + "\n", + "# Customize the plot\n", + "plt.title('Price Over Time')\n", + "plt.xlabel('Date')\n", + "plt.ylabel('Price')\n", + "\n", + "# Rotate x-axis labels for better readability\n", + "plt.xticks(rotation=45)\n", + "\n", + "# Adjust layout to prevent label cutoff\n", + "plt.tight_layout()\n", + "\n", + "# Show the plot\n", + "plt.show()" + ] + }, { "cell_type": "markdown", "id": "d1c2e4b5", @@ -638,7 +2649,7 @@ ], "metadata": { "kernelspec": { - "display_name": "tda", + "display_name": "Python 3", "language": "python", "name": "python3" }, @@ -652,7 +2663,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.11" + "version": "3.9.6" } }, "nbformat": 4, diff --git a/.ipynb_checkpoints/sp500-checkpoint.csv b/.ipynb_checkpoints/sp500-checkpoint.csv new file mode 100644 index 0000000..a958c1c --- /dev/null +++ b/.ipynb_checkpoints/sp500-checkpoint.csv @@ -0,0 +1,83 @@ +1253.755 +1269.825 +1284.185 +1274.11 +1279.99 +1300.9025 +1295.175 +1284.985 +1286.2175 +1296.37 +1288.3275 +1269.1575 +1270.7875 +1272.62 +1286.45 +1276.7225 +1269.38 +1277.33 +1293.2875 +1289.245 +1287.7875 +1274.05 +1251.88 +1233.35 +1265.9375 +1245.7725 +1233.3775 +1231.3775 +1244.8425 +1212.37 +1191.7475 +1178.125 +1182.3375 +1249.6075 +1228.485 +1201.7175 +1187.6325 +1201.2375 +1200.965 +1152.5775 +1145.7925 +1155.89 +1134.3 +1119.885 +1057.0025 +1033.425 +985.7825 +955.645 +885.4275 +966.9125 +1016.02 +945.4125 +918.0025 +941.66 +967.3075 +966 +913.97 +898.3725 +869.6925 +862.42 +899.8525 +939.895 +950.9775 +962.6375 +967.2325 +993.3625 +973.925 +924.9375 +921.005 +932.0925 +901.625 +869.08 +875.0125 +887.8075 +861.0275 +850.2925 +833.7525 +779.1075 +776.425 +834.205 +857.45 +864.3525 +889.2825 \ No newline at end of file diff --git a/.ipynb_checkpoints/sp500_full-checkpoint.csv b/.ipynb_checkpoints/sp500_full-checkpoint.csv new file mode 100644 index 0000000..3cf0308 --- /dev/null +++ b/.ipynb_checkpoints/sp500_full-checkpoint.csv @@ -0,0 +1,5536 @@ +03/01/2000,1460.2 +04/01/2000,1426.8 +05/01/2000,1398.125 +06/01/2000,1402.375 +07/01/2000,1421.75 +10/01/2000,1451.25 +11/01/2000,1447.35 +12/01/2000,1435.975 +13/01/2000,1442.175 +14/01/2000,1459.4 +18/01/2000,1459.175 +19/01/2000,1455.475 +20/01/2000,1451.425 +21/01/2000,1444.825 +24/01/2000,1423.125 +25/01/2000,1403.575 +26/01/2000,1406.675 +27/01/2000,1400.55 +28/01/2000,1378.375 +31/01/2000,1374.8 +01/02/2000,1400.3 +02/02/2000,1410.525 +03/02/2000,1414.6 +04/02/2000,1426.475 +07/02/2000,1422.275 +08/02/2000,1433.025 +09/02/2000,1427.75 +10/02/2000,1414.225 +11/02/2000,1399.975 +14/02/2000,1388.1 +15/02/2000,1393.975 +16/02/2000,1395 +17/02/2000,1388.975 +18/02/2000,1367 +22/02/2000,1347.1 +23/02/2000,1356.35 +24/02/2000,1352.125 +25/02/2000,1344.5 +28/02/2000,1341.8 +29/02/2000,1357.975 +01/03/2000,1373.75 +02/03/2000,1379.55 +03/03/2000,1395.925 +06/03/2000,1398.775 +07/03/2000,1374.025 +08/03/2000,1360.6 +09/03/2000,1382 +10/03/2000,1400.575 +13/03/2000,1385.625 +14/03/2000,1374.3 +15/03/2000,1376.6 +16/03/2000,1425.35 +17/03/2000,1463.2 +20/03/2000,1459.925 +21/03/2000,1472.6 +22/03/2000,1496.725 +23/03/2000,1513.45 +24/03/2000,1531.175 +27/03/2000,1526.175 +28/03/2000,1516.5 +29/03/2000,1508.725 +30/03/2000,1497.1 +31/03/2000,1497.7 +03/04/2000,1499.7 +04/04/2000,1486.025 +05/04/2000,1491.675 +06/04/2000,1496.975 +07/04/2000,1509.4 +10/04/2000,1512.725 +11/04/2000,1501.175 +12/04/2000,1486.15 +13/04/2000,1456.35 +14/04/2000,1394.25 +17/04/2000,1376.55 +18/04/2000,1420.55 +19/04/2000,1435.525 +20/04/2000,1429.85 +24/04/2000,1426.525 +25/04/2000,1453.725 +26/04/2000,1469.625 +27/04/2000,1457.45 +28/04/2000,1459.8 +01/05/2000,1463.6 +02/05/2000,1456.95 +03/05/2000,1426.525 +04/05/2000,1412.55 +05/05/2000,1420.825 +08/05/2000,1426.575 +09/05/2000,1417 +10/05/2000,1395.6 +11/05/2000,1396 +12/05/2000,1416.7 +15/05/2000,1435.7 +16/05/2000,1459.9 +17/05/2000,1455.35 +18/05/2000,1444.925 +19/05/2000,1420.775 +22/05/2000,1396.65 +23/05/2000,1387.95 +24/05/2000,1383.875 +25/05/2000,1391.6 +26/05/2000,1380.2 +30/05/2000,1400.2 +31/05/2000,1423.25 +01/06/2000,1434.7 +02/06/2000,1464.575 +05/06/2000,1471.725 +06/06/2000,1462.875 +07/06/2000,1464.75 +08/06/2000,1466.3 +09/06/2000,1461.575 +12/06/2000,1453 +13/06/2000,1457.075 +14/06/2000,1472.825 +15/06/2000,1473.925 +16/06/2000,1471.125 +19/06/2000,1474.625 +20/06/2000,1479.85 +21/06/2000,1476.45 +22/06/2000,1464.625 +23/06/2000,1447.95 +26/06/2000,1450.15 +27/06/2000,1454.9 +28/06/2000,1455.85 +29/06/2000,1446.75 +30/06/2000,1447.625 +03/07/2000,1461.175 +05/07/2000,1456.925 +06/07/2000,1451.05 +07/07/2000,1469.375 +10/07/2000,1478.925 +11/07/2000,1478.975 +12/07/2000,1488.05 +13/07/2000,1494.95 +14/07/2000,1502.625 +17/07/2000,1510.75 +18/07/2000,1501.525 +19/07/2000,1487.75 +20/07/2000,1490.375 +21/07/2000,1487.35 +24/07/2000,1473.525 +25/07/2000,1469.85 +26/07/2000,1463.45 +27/07/2000,1453.025 +28/07/2000,1435 +31/07/2000,1426.65 +01/08/2000,1435.3 +02/08/2000,1440.475 +03/08/2000,1442.9 +04/08/2000,1457.475 +07/08/2000,1470.975 +08/08/2000,1479.8 +09/08/2000,1479.3 +10/08/2000,1467.05 +11/08/2000,1465.125 +14/08/2000,1480.9 +15/08/2000,1487.95 +16/08/2000,1483.675 +17/08/2000,1488.8 +18/08/2000,1494.05 +21/08/2000,1496.325 +22/08/2000,1500.85 +23/08/2000,1500.2 +24/08/2000,1506.7 +25/08/2000,1508.35 +28/08/2000,1512.875 +29/08/2000,1511.05 +30/08/2000,1505.725 +31/08/2000,1512.05 +01/09/2000,1521.025 +05/09/2000,1513.225 +06/09/2000,1500.975 +07/09/2000,1498.025 +08/09/2000,1497.35 +11/09/2000,1493.35 +12/09/2000,1486.95 +13/09/2000,1482.075 +14/09/2000,1484.225 +15/09/2000,1471.975 +18/09/2000,1455 +19/09/2000,1452.475 +20/09/2000,1450.725 +21/09/2000,1447.35 +22/09/2000,1442.25 +25/09/2000,1445.3 +26/09/2000,1434.8 +27/09/2000,1427.5 +28/09/2000,1443.1 +29/09/2000,1447.4 +02/10/2000,1437 +03/10/2000,1435.7 +04/10/2000,1429.275 +05/10/2000,1436.65 +06/10/2000,1421.425 +09/10/2000,1403.3 +10/10/2000,1395.4 +11/10/2000,1372.075 +12/10/2000,1349.35 +13/10/2000,1351.25 +16/10/2000,1373.35 +17/10/2000,1361.975 +18/10/2000,1338.65 +19/10/2000,1365.725 +20/10/2000,1394.1 +23/10/2000,1396.875 +24/10/2000,1399.4 +25/10/2000,1380.825 +26/10/2000,1359.95 +27/10/2000,1373.175 +30/10/2000,1390.4 +31/10/2000,1414.75 +01/11/2000,1422.675 +02/11/2000,1425.975 +03/11/2000,1427.275 +06/11/2000,1431.8 +07/11/2000,1430.9 +08/11/2000,1421.825 +09/11/2000,1397.1 +10/11/2000,1383.05 +13/11/2000,1352.975 +14/11/2000,1368.925 +15/11/2000,1385.9 +16/11/2000,1381.8 +17/11/2000,1370.075 +20/11/2000,1354.925 +21/11/2000,1344.85 +22/11/2000,1334.725 +24/11/2000,1332.6 +27/11/2000,1348.775 +28/11/2000,1344.725 +29/11/2000,1339.925 +30/11/2000,1323.425 +01/12/2000,1317.975 +04/12/2000,1320.625 +05/12/2000,1350.775 +06/12/2000,1362.675 +07/12/2000,1346.95 +08/12/2000,1359.3 +11/12/2000,1375.8 +12/12/2000,1375.5 +13/12/2000,1368.875 +14/12/2000,1350.35 +15/12/2000,1324.85 +18/12/2000,1319.85 +19/12/2000,1320.05 +20/12/2000,1284.275 +21/12/2000,1269.75 +22/12/2000,1290.45 +26/12/2000,1309.675 +27/12/2000,1321.775 +28/12/2000,1331.2 +29/12/2000,1328.025 +02/01/2001,1299.975 +03/01/2001,1313.325 +04/01/2001,1340.05 +05/01/2001,1315.35 +08/01/2001,1292.2 +09/01/2001,1300.875 +10/01/2001,1303.8 +11/01/2001,1320.5 +12/01/2001,1322.475 +16/01/2001,1321.525 +17/01/2001,1332.125 +18/01/2001,1339.5 +19/01/2001,1345.425 +22/01/2001,1343.2 +23/01/2001,1351.45 +24/01/2001,1362.95 +25/01/2001,1360.925 +26/01/2001,1353.2 +29/01/2001,1358.75 +30/01/2001,1367.45 +31/01/2001,1371.95 +01/02/2001,1368.075 +02/02/2001,1362.025 +05/02/2001,1350.725 +06/02/2001,1355.025 +07/02/2001,1344.95 +08/02/2001,1339.075 +09/02/2001,1322.45 +12/02/2001,1322.425 +13/02/2001,1325.8 +14/02/2001,1315.025 +15/02/2001,1322.425 +16/02/2001,1311.975 +20/02/2001,1291.5 +21/02/2001,1267.6 +22/02/2001,1249.075 +23/02/2001,1241.725 +26/02/2001,1255.75 +27/02/2001,1262.675 +28/02/2001,1247.75 +01/03/2001,1234.25 +02/03/2001,1236.525 +05/03/2001,1238.025 +06/03/2001,1251 +07/03/2001,1258.35 +08/03/2001,1262.675 +09/03/2001,1247.8 +12/03/2001,1205.95 +13/03/2001,1186.8 +14/03/2001,1179.35 +15/03/2001,1172.25 +16/03/2001,1161.575 +19/03/2001,1160.5 +20/03/2001,1159.05 +21/03/2001,1133.2 +22/03/2001,1111.3 +23/03/2001,1129.2 +26/03/2001,1148.075 +27/03/2001,1167.325 +28/03/2001,1166.375 +29/03/2001,1149.825 +30/03/2001,1153.725 +02/04/2001,1153.3 +03/04/2001,1124.625 +04/04/2001,1104.8 +05/04/2001,1127.325 +06/04/2001,1137.625 +09/04/2001,1134.625 +10/04/2001,1154.375 +11/04/2001,1169.2 +12/04/2001,1172.65 +16/04/2001,1178.8 +17/04/2001,1183.15 +18/04/2001,1217.55 +19/04/2001,1244.75 +20/04/2001,1246.2 +23/04/2001,1231.975 +24/04/2001,1219.075 +25/04/2001,1219.525 +26/04/2001,1235.1 +27/04/2001,1243.775 +30/04/2001,1253.95 +01/05/2001,1256.475 +02/05/2001,1266.1 +03/05/2001,1255.825 +04/05/2001,1253.675 +07/05/2001,1264.825 +08/05/2001,1261.975 +09/05/2001,1256.55 +10/05/2001,1258.35 +11/05/2001,1250.375 +14/05/2001,1246.325 +15/05/2001,1250.3 +16/05/2001,1265.95 +17/05/2001,1288.175 +18/05/2001,1288.45 +21/05/2001,1301.425 +22/05/2001,1311.25 +23/05/2001,1299.125 +24/05/2001,1289.6 +25/05/2001,1285.175 +29/05/2001,1272.4 +30/05/2001,1257.475 +31/05/2001,1253.475 +01/06/2001,1257.175 +04/06/2001,1262.85 +05/06/2001,1276.1 +06/06/2001,1276.6 +07/06/2001,1272.3 +08/06/2001,1269.775 +11/06/2001,1258.4 +12/06/2001,1251.75 +13/06/2001,1249.7 +14/06/2001,1230.5 +15/06/2001,1214.7 +18/06/2001,1213.075 +19/06/2001,1213.7 +20/06/2001,1217.85 +21/06/2001,1230.125 +22/06/2001,1230.35 +25/06/2001,1222.25 +26/06/2001,1215.175 +27/06/2001,1213.775 +28/06/2001,1220.7 +29/06/2001,1227.25 +02/07/2001,1231.225 +03/07/2001,1234.325 +05/07/2001,1226.85 +06/07/2001,1204.425 +09/07/2001,1195.25 +10/07/2001,1190.9 +11/07/2001,1178.775 +12/07/2001,1194.675 +13/07/2001,1211.475 +16/07/2001,1209.45 +17/07/2001,1207.1 +18/07/2001,1208.7 +19/07/2001,1213.375 +20/07/2001,1212.125 +23/07/2001,1201.875 +24/07/2001,1179.8 +25/07/2001,1181 +26/07/2001,1195.075 +27/07/2001,1203.5 +30/07/2001,1204.925 +31/07/2001,1210.725 +01/08/2001,1215.325 +02/08/2001,1219.575 +03/08/2001,1215.3 +06/08/2001,1206.6 +07/08/2001,1202.025 +08/08/2001,1194 +09/08/2001,1181.575 +10/08/2001,1184.1 +13/08/2001,1190.1 +14/08/2001,1190.275 +15/08/2001,1183.375 +16/08/2001,1176.9 +17/08/2001,1170.375 +20/08/2001,1166.425 +21/08/2001,1166.275 +22/08/2001,1161.125 +23/08/2001,1164.575 +24/08/2001,1173.575 +27/08/2001,1182.25 +28/08/2001,1170.4 +29/08/2001,1156.125 +30/08/2001,1138.575 +31/08/2001,1132.7 +04/09/2001,1137.75 +05/09/2001,1128.75 +06/09/2001,1118.9 +07/09/2001,1095.175 +10/09/2001,1087.1 +17/09/2001,1065.325 +18/09/2001,1036.775 +19/09/2001,1018.075 +20/09/2001,1000.3 +21/09/2001,969.9 +24/09/2001,985.875 +25/09/2001,1007.8 +26/09/2001,1010.55 +27/09/2001,1010.675 +28/09/2001,1032.225 +01/10/2001,1036.025 +02/10/2001,1043.675 +03/10/2001,1058.025 +04/10/2001,1073.45 +05/10/2001,1066.7 +08/10/2001,1062.75 +09/10/2001,1059.225 +10/10/2001,1067.65 +11/10/2001,1089.65 +12/10/2001,1087.425 +15/10/2001,1085.825 +16/10/2001,1095 +17/10/2001,1092.1 +18/10/2001,1071.35 +19/10/2001,1068.2 +22/10/2001,1081.075 +23/10/2001,1089.8 +24/10/2001,1085.175 +25/10/2001,1084.625 +26/10/2001,1101.4 +29/10/2001,1090.25 +30/10/2001,1067.5 +31/10/2001,1064.625 +01/11/2001,1071.775 +02/11/2001,1083.225 +05/11/2001,1095.975 +06/11/2001,1109.2 +07/11/2001,1118.575 +08/11/2001,1121.375 +09/11/2001,1118 +12/11/2001,1112.75 +13/11/2001,1128.7 +14/11/2001,1142.175 +15/11/2001,1141.25 +16/11/2001,1138.575 +19/11/2001,1146.2 +20/11/2001,1146.6 +21/11/2001,1137.425 +23/11/2001,1143.55 +26/11/2001,1152.95 +27/11/2001,1151.45 +28/11/2001,1137.35 +29/11/2001,1134.275 +30/11/2001,1139.75 +03/12/2001,1133.675 +04/12/2001,1138.25 +05/12/2001,1159.775 +06/12/2001,1168.225 +07/12/2001,1160.15 +10/12/2001,1147.575 +11/12/2001,1140.475 +12/12/2001,1136 +13/12/2001,1125.475 +14/12/2001,1120.95 +17/12/2001,1129.3 +18/12/2001,1139.2 +19/12/2001,1143.275 +20/12/2001,1145.025 +21/12/2001,1143.125 +24/12/2001,1145.525 +26/12/2001,1149.5 +27/12/2001,1153.25 +28/12/2001,1159.95 +31/12/2001,1153.9 +02/01/2002,1148.65 +03/01/2002,1160.025 +04/01/2002,1170.875 +07/01/2002,1170.025 +08/01/2002,1162.775 +09/01/2002,1161.275 +10/01/2002,1155.375 +11/01/2002,1152.25 +14/01/2002,1141.3 +15/01/2002,1143.175 +16/01/2002,1135.125 +17/01/2002,1135.375 +18/01/2002,1129.625 +22/01/2002,1126.95 +23/01/2002,1124.925 +24/01/2002,1133.325 +25/01/2002,1132.175 +28/01/2002,1133.675 +29/01/2002,1117.65 +30/01/2002,1102.325 +31/01/2002,1122.875 +01/02/2002,1124.575 +04/02/2002,1106.7 +05/02/2002,1090.575 +06/02/2002,1086.6 +07/02/2002,1083.975 +08/02/2002,1088.7 +11/02/2002,1103.5 +12/02/2002,1107.35 +13/02/2002,1113.525 +14/02/2002,1118 +15/02/2002,1110.3 +19/02/2002,1092.475 +20/02/2002,1088.85 +21/02/2002,1089.25 +22/02/2002,1084.075 +25/02/2002,1100.675 +26/02/2002,1109.1 +27/02/2002,1111.625 +28/02/2002,1111.45 +01/03/2002,1120.25 +04/03/2002,1142.35 +05/03/2002,1150.4 +06/03/2002,1154.775 +07/03/2002,1160.2 +08/03/2002,1164.5 +11/03/2002,1166.225 +12/03/2002,1164.125 +13/03/2002,1158.1 +14/03/2002,1154.025 +15/03/2002,1159.925 +18/03/2002,1165.875 +19/03/2002,1168.8 +20/03/2002,1160.95 +21/03/2002,1150.025 +22/03/2002,1150.775 +25/03/2002,1141.025 +26/03/2002,1137.175 +27/03/2002,1141.1 +28/03/2002,1148.2 +01/04/2002,1143.3 +02/04/2002,1139.625 +03/04/2002,1130.35 +04/04/2002,1125.475 +05/04/2002,1125.8 +08/04/2002,1121.3 +09/04/2002,1122.075 +10/04/2002,1124.95 +11/04/2002,1116.775 +12/04/2002,1107.55 +15/04/2002,1106.95 +16/04/2002,1115.7 +17/04/2002,1127.7 +18/04/2002,1122.65 +19/04/2002,1125.3 +22/04/2002,1115.95 +23/04/2002,1104.725 +24/04/2002,1098.775 +25/04/2002,1090.95 +26/04/2002,1085.225 +29/04/2002,1071.1 +30/04/2002,1072.125 +01/05/2002,1079.25 +02/05/2002,1085.5 +03/05/2002,1077.875 +06/05/2002,1063.675 +07/05/2002,1052.475 +08/05/2002,1069.175 +09/05/2002,1080.7 +10/05/2002,1064.325 +13/05/2002,1064.575 +14/05/2002,1086.05 +15/05/2002,1095.375 +16/05/2002,1094.45 +17/05/2002,1102.05 +20/05/2002,1098.925 +21/05/2002,1087.6 +22/05/2002,1081.875 +23/05/2002,1090.175 +24/05/2002,1090.05 +28/05/2002,1078.65 +29/05/2002,1071.175 +30/05/2002,1064.05 +31/05/2002,1069.1 +03/06/2002,1054.6 +04/06/2002,1039.5 +05/06/2002,1044.875 +06/06/2002,1038.975 +07/06/2002,1025.55 +10/06/2002,1030.475 +11/06/2002,1024.05 +12/06/2002,1014.6 +13/06/2002,1015.375 +14/06/2002,1002.025 +17/06/2002,1021.75 +18/06/2002,1036.25 +19/06/2002,1028.15 +20/06/2002,1013.55 +21/06/2002,996.825 +24/06/2002,988.7 +25/06/2002,987.225 +26/06/2002,969.975 +27/06/2002,979.625 +28/06/2002,992.625 +01/07/2002,980.075 +02/07/2002,957.7 +03/07/2002,947.825 +05/07/2002,974.475 +08/07/2002,983.125 +09/07/2002,965.275 +10/07/2002,937.475 +11/07/2002,919.5 +12/07/2002,924.2 +15/07/2002,909.3 +16/07/2002,908.65 +17/07/2002,907.125 +18/07/2002,894 +19/07/2002,858.9 +22/07/2002,833.775 +23/07/2002,810.35 +24/07/2002,815.275 +25/07/2002,838 +26/07/2002,845.075 +29/07/2002,875.9 +30/07/2002,899.075 +31/07/2002,903.975 +01/08/2002,897.625 +02/08/2002,871.9 +05/08/2002,849.1 +06/08/2002,850.8 +07/08/2002,867.3 +08/08/2002,890.825 +09/08/2002,904.725 +12/08/2002,903.35 +13/08/2002,895.825 +14/08/2002,900.05 +15/08/2002,925.325 +16/08/2002,927.65 +19/08/2002,939.475 +20/08/2002,942.675 +21/08/2002,942.425 +22/08/2002,955.875 +23/08/2002,950.875 +26/08/2002,942.525 +27/08/2002,942.25 +28/08/2002,925.175 +29/08/2002,915.9 +30/08/2002,918.05 +03/09/2002,896.925 +04/09/2002,885.8 +05/09/2002,884.1 +06/09/2002,887.8 +09/09/2002,896.775 +10/09/2002,905.75 +11/09/2002,913.15 +12/09/2002,897.675 +13/09/2002,886.625 +16/09/2002,887.9 +17/09/2002,884.925 +18/09/2002,869.725 +19/09/2002,856.35 +20/09/2002,844.275 +23/09/2002,837.575 +24/09/2002,826.025 +25/09/2002,830.425 +26/09/2002,847.75 +27/09/2002,841.05 +30/09/2002,817.575 +01/10/2002,830.975 +02/10/2002,837.525 +03/10/2002,826.025 +04/10/2002,809.9 +07/10/2002,794.275 +08/10/2002,793.05 +09/10/2002,787.4 +10/10/2002,788.95 +11/10/2002,821.6 +14/10/2002,837.375 +15/10/2002,861.35 +16/10/2002,869.725 +17/10/2002,871.15 +18/10/2002,879.225 +21/10/2002,889.475 +22/10/2002,893 +23/10/2002,889.05 +24/10/2002,890.125 +25/10/2002,888.7 +28/10/2002,895.325 +29/10/2002,882.7 +30/10/2002,886.825 +31/10/2002,888.775 +01/11/2002,891.975 +04/11/2002,908.75 +05/11/2002,911.125 +06/11/2002,917.475 +07/11/2002,912.225 +08/11/2002,899.75 +11/11/2002,885.05 +12/11/2002,882.425 +13/11/2002,882.5 +14/11/2002,893.4 +15/11/2002,904.925 +18/11/2002,906.4 +19/11/2002,898.925 +20/11/2002,905.175 +21/11/2002,924.275 +22/11/2002,932.5 +25/11/2002,930.95 +26/11/2002,922.8 +27/11/2002,926.475 +29/11/2002,938.15 +02/12/2002,938.2 +03/12/2002,927.125 +04/12/2002,918.275 +05/12/2002,912.875 +06/12/2002,907.55 +09/12/2002,902.1 +10/12/2002,898.375 +11/12/2002,903.975 +12/12/2002,903 +13/12/2002,895.3 +16/12/2002,899.95 +17/12/2002,906.575 +18/12/2002,896.225 +19/12/2002,888.425 +20/12/2002,890.5 +23/12/2002,896.95 +24/12/2002,894.9 +26/12/2002,893.4 +27/12/2002,882.3 +30/12/2002,876.775 +31/12/2002,877.65 +02/01/2003,894.4 +03/01/2003,907.975 +06/01/2003,919.5 +07/01/2003,925.65 +08/01/2003,916 +09/01/2003,918.925 +10/01/2003,926.45 +13/01/2003,927.725 +14/01/2003,927.85 +15/01/2003,924.8 +16/01/2003,917.7 +17/01/2003,907.5 +21/01/2003,895.75 +22/01/2003,883.325 +23/01/2003,883.2 +24/01/2003,873.925 +27/01/2003,854.275 +28/01/2003,853.575 +29/01/2003,859.375 +30/01/2003,854.55 +31/01/2003,849.725 +03/02/2003,859.075 +04/02/2003,852.25 +05/02/2003,848.875 +06/02/2003,839.775 +07/02/2003,835.05 +10/02/2003,831.6 +11/02/2003,833.325 +12/02/2003,824.625 +13/02/2003,815.9 +14/02/2003,825.55 +18/02/2003,843.475 +19/02/2003,846.575 +20/02/2003,842.05 +21/02/2003,842.275 +24/02/2003,840.3 +25/02/2003,832.3 +26/02/2003,833.225 +27/02/2003,833.625 +28/02/2003,840.675 +03/03/2003,840.225 +04/03/2003,828.55 +05/03/2003,825.2 +06/03/2003,825.45 +07/03/2003,822.925 +10/03/2003,817.975 +11/03/2003,805.675 +12/03/2003,799.5 +13/03/2003,818.075 +14/03/2003,833.725 +17/03/2003,846.525 +18/03/2003,863.4 +19/03/2003,869.175 +20/03/2003,872.075 +21/03/2003,885.825 +24/03/2003,879.45 +25/03/2003,870.35 +26/03/2003,871.75 +27/03/2003,867.675 +28/03/2003,865.675 +31/03/2003,854.725 +01/04/2003,853.975 +02/04/2003,870.625 +03/04/2003,879.85 +04/04/2003,878.075 +07/04/2003,885.65 +08/04/2003,879 +09/04/2003,874.35 +10/04/2003,868.05 +11/04/2003,872.275 +14/04/2003,876.775 +15/04/2003,887.3 +16/04/2003,886.35 +17/04/2003,886.625 +21/04/2003,892.95 +22/04/2003,900.45 +23/04/2003,915 +24/04/2003,914.025 +25/04/2003,904.775 +28/04/2003,907.625 +29/04/2003,916.975 +30/04/2003,917.1 +01/05/2003,913.925 +02/05/2003,922.35 +05/05/2003,928.75 +06/05/2003,931.725 +07/05/2003,931.9 +08/05/2003,924.8 +09/05/2003,926.95 +12/05/2003,938.65 +13/05/2003,943.45 +14/05/2003,941.025 +15/05/2003,943.25 +16/05/2003,943.775 +19/05/2003,932.4 +20/05/2003,919.45 +21/05/2003,920.475 +22/05/2003,928.275 +23/05/2003,931.925 +27/05/2003,941.2 +28/05/2003,953.55 +29/05/2003,952.775 +30/05/2003,957.05 +02/06/2003,968.325 +03/06/2003,969.025 +04/06/2003,979.1 +05/06/2003,986.125 +06/06/2003,992.9 +09/06/2003,981.025 +10/06/2003,980.35 +11/06/2003,990.35 +12/06/2003,997.5 +13/06/2003,993.075 +16/06/2003,999.7 +17/06/2003,1011.175 +18/06/2003,1010.375 +19/06/2003,1002.275 +20/06/2003,996.475 +23/06/2003,987.6 +24/06/2003,983 +25/06/2003,981.325 +26/06/2003,980.35 +27/06/2003,981.3 +30/06/2003,976.975 +01/07/2003,975.55 +02/07/2003,988.05 +03/07/2003,989.45 +07/07/2003,995.35 +08/07/2003,1004.95 +09/07/2003,1004.65 +10/07/2003,994.175 +11/07/2003,994.1 +14/07/2003,1003.875 +15/07/2003,1002.65 +16/07/2003,996.8 +17/07/2003,987.075 +18/07/2003,987.725 +21/07/2003,985.25 +22/07/2003,983.325 +23/07/2003,986.6 +24/07/2003,987.55 +25/07/2003,989.1 +28/07/2003,997.375 +29/07/2003,992.125 +30/07/2003,988.85 +31/07/2003,992.475 +01/08/2003,984.9 +04/08/2003,978.875 +05/08/2003,974.025 +06/08/2003,967.275 +07/08/2003,969.975 +08/08/2003,976.525 +11/08/2003,979.475 +12/08/2003,985.325 +13/08/2003,986.95 +14/08/2003,986.7 +15/08/2003,989.55 +18/08/2003,995.375 +19/08/2003,1000.175 +20/08/2003,1000.7 +21/08/2003,1003.1 +22/08/2003,1000 +25/08/2003,992.1 +26/08/2003,992.975 +27/08/2003,996.2 +28/08/2003,998.775 +29/08/2003,1004.8 +02/09/2003,1014.575 +03/09/2003,1024.9 +04/09/2003,1026.425 +05/09/2003,1024.2 +08/09/2003,1026.7 +09/09/2003,1026.875 +10/09/2003,1016.75 +11/09/2003,1014.775 +12/09/2003,1015.575 +15/09/2003,1016.7 +16/09/2003,1022.15 +17/09/2003,1027.775 +18/09/2003,1032.9 +19/09/2003,1037.025 +22/09/2003,1028.425 +23/09/2003,1025.85 +24/09/2003,1019.275 +25/09/2003,1008 +26/09/2003,999.95 +29/09/2003,1001.425 +30/09/2003,999.9 +01/10/2003,1007.1 +02/10/2003,1018.425 +03/10/2003,1027.375 +06/10/2003,1032.45 +07/10/2003,1034.725 +08/10/2003,1036.025 +09/10/2003,1038.65 +10/10/2003,1038.325 +13/10/2003,1042.6 +14/10/2003,1046.275 +15/10/2003,1048.325 +16/10/2003,1048.45 +17/10/2003,1044.475 +20/10/2003,1041.2 +21/10/2003,1045.45 +22/10/2003,1037.7 +23/10/2003,1031.375 +24/10/2003,1028.7 +27/10/2003,1031.675 +28/10/2003,1038.95 +29/10/2003,1047 +30/10/2003,1047.9 +31/10/2003,1049.4 +03/11/2003,1055.45 +04/11/2003,1055.725 +05/11/2003,1051.1 +06/11/2003,1053.9 +07/11/2003,1056.45 +10/11/2003,1049.9 +11/11/2003,1046.35 +12/11/2003,1052.725 +13/11/2003,1057.4 +14/11/2003,1055.125 +17/11/2003,1044.875 +18/11/2003,1040.15 +19/11/2003,1038.7 +20/11/2003,1039 +21/11/2003,1034.45 +24/11/2003,1043.7 +25/11/2003,1053.325 +26/11/2003,1054.8 +28/11/2003,1058.525 +01/12/2003,1064.25 +02/12/2003,1068.275 +03/12/2003,1067.55 +04/12/2003,1067 +05/12/2003,1065.25 +08/12/2003,1065.325 +09/12/2003,1065.15 +10/12/2003,1058.9 +11/12/2003,1065.7 +12/12/2003,1071.925 +15/12/2003,1073.225 +16/12/2003,1071.75 +17/12/2003,1074.8 +18/12/2003,1082.925 +19/12/2003,1088.3 +22/12/2003,1090.15 +23/12/2003,1094.4 +24/12/2003,1094.775 +26/12/2003,1095.6 +29/12/2003,1102.7 +30/12/2003,1108.825 +31/12/2003,1110.075 +02/01/2004,1111.075 +05/01/2004,1115.35 +06/01/2004,1122.2 +07/01/2004,1123.2 +08/01/2004,1128.75 +09/01/2004,1126.65 +12/01/2004,1124.45 +13/01/2004,1123.175 +14/01/2004,1125.925 +15/01/2004,1131.025 +16/01/2004,1135.9 +20/01/2004,1139.225 +21/01/2004,1142.55 +22/01/2004,1146.25 +23/01/2004,1143.125 +26/01/2004,1148.325 +27/01/2004,1149.7 +28/01/2004,1137.025 +29/01/2004,1129.85 +30/01/2004,1131.775 +02/02/2004,1134.225 +03/02/2004,1135 +04/02/2004,1130.8 +05/02/2004,1127.675 +06/02/2004,1135.65 +09/02/2004,1141.575 +10/02/2004,1142.75 +11/02/2004,1151.125 +12/02/2004,1154.775 +13/02/2004,1149.5 +17/02/2004,1151.9 +18/02/2004,1153.9 +19/02/2004,1151.075 +20/02/2004,1145 +23/02/2004,1142.2 +24/02/2004,1139.75 +25/02/2004,1141.675 +26/02/2004,1143.6 +27/02/2004,1146.05 +01/03/2004,1150.825 +02/03/2004,1152.225 +03/03/2004,1149.075 +04/03/2004,1152.675 +05/03/2004,1155.925 +08/03/2004,1152.75 +09/03/2004,1142.975 +10/03/2004,1132.125 +11/03/2004,1115.65 +12/03/2004,1113.7 +15/03/2004,1112.275 +16/03/2004,1107.9 +17/03/2004,1117.75 +18/03/2004,1121.2 +19/03/2004,1116.125 +22/03/2004,1101.125 +23/03/2004,1095.625 +24/03/2004,1092.7 +25/03/2004,1100.55 +26/03/2004,1109.675 +29/03/2004,1115.775 +30/03/2004,1124.2 +31/03/2004,1126.375 +01/04/2004,1130.075 +02/04/2004,1137.75 +05/04/2004,1146.15 +06/04/2004,1148.175 +07/04/2004,1143.825 +08/04/2004,1140.825 +12/04/2004,1142.775 +13/04/2004,1137.525 +14/04/2004,1128.075 +15/04/2004,1127.975 +16/04/2004,1131.75 +19/04/2004,1134.1 +20/04/2004,1127.85 +21/04/2004,1121 +22/04/2004,1132.175 +23/04/2004,1139.3 +26/04/2004,1138.525 +27/04/2004,1138.975 +28/04/2004,1130.075 +29/04/2004,1118.275 +30/04/2004,1111.925 +03/05/2004,1112.7 +04/05/2004,1119.4 +05/05/2004,1121 +06/05/2004,1115.825 +07/05/2004,1107.15 +10/05/2004,1091.025 +11/05/2004,1091.35 +12/05/2004,1091.65 +13/05/2004,1097.075 +14/05/2004,1095.675 +17/05/2004,1088.725 +18/05/2004,1088.45 +19/05/2004,1093.65 +20/05/2004,1088.975 +21/05/2004,1092.925 +24/05/2004,1095.625 +25/05/2004,1103.225 +26/05/2004,1113.625 +27/05/2004,1118.775 +28/05/2004,1120.7 +01/06/2004,1119.475 +02/06/2004,1123.225 +03/06/2004,1120.875 +04/06/2004,1121.225 +07/06/2004,1131.475 +08/06/2004,1140.075 +09/06/2004,1136.725 +10/06/2004,1133.9 +14/06/2004,1130.125 +15/06/2004,1130 +16/06/2004,1132.85 +17/06/2004,1131.525 +18/06/2004,1133.975 +21/06/2004,1133.225 +22/06/2004,1131.025 +23/06/2004,1138.85 +24/06/2004,1142.75 +25/06/2004,1138.825 +28/06/2004,1135.475 +29/06/2004,1134.9 +30/06/2004,1138.7 +01/07/2004,1133.4 +02/07/2004,1126.7 +06/07/2004,1120.05 +07/07/2004,1117.95 +08/07/2004,1113.8 +09/07/2004,1111.65 +12/07/2004,1112.475 +13/07/2004,1114.675 +14/07/2004,1113.5 +15/07/2004,1109.875 +16/07/2004,1105.35 +19/07/2004,1101.075 +20/07/2004,1104.4 +21/07/2004,1103.2 +22/07/2004,1093.65 +23/07/2004,1090.825 +26/07/2004,1084.725 +27/07/2004,1089.925 +28/07/2004,1092.8 +29/07/2004,1098.725 +30/07/2004,1100.7 +02/08/2004,1103.55 +03/08/2004,1103.025 +04/08/2004,1098.3 +05/08/2004,1089.525 +06/08/2004,1071.9 +09/08/2004,1065.675 +10/08/2004,1072.1 +11/08/2004,1074.925 +12/08/2004,1069.4 +13/08/2004,1064.075 +16/08/2004,1072.4 +17/08/2004,1081.825 +18/08/2004,1087.75 +19/08/2004,1091.975 +20/08/2004,1094.85 +23/08/2004,1097.525 +24/08/2004,1096.4 +25/08/2004,1100.175 +26/08/2004,1104.825 +27/08/2004,1106.8 +30/08/2004,1103.5 +31/08/2004,1100.575 +01/09/2004,1104.6 +02/09/2004,1112.225 +03/09/2004,1116.575 +07/09/2004,1118.15 +08/09/2004,1119.225 +09/09/2004,1117.4 +10/09/2004,1120.5 +13/09/2004,1125.7 +14/09/2004,1127.075 +15/09/2004,1124.175 +16/09/2004,1122.6 +17/09/2004,1126.5 +20/09/2004,1124.875 +21/09/2004,1126.3 +22/09/2004,1121.225 +23/09/2004,1110.9 +24/09/2004,1110.175 +27/09/2004,1106.725 +28/09/2004,1106.675 +29/09/2004,1111.775 +30/09/2004,1113.825 +01/10/2004,1123.075 +04/10/2004,1134.6 +05/10/2004,1134.9 +06/10/2004,1137.85 +07/10/2004,1136.3 +08/10/2004,1126.475 +11/10/2004,1123.7 +12/10/2004,1121.6 +13/10/2004,1118.025 +14/10/2004,1108.525 +15/10/2004,1106.7 +18/10/2004,1110 +19/10/2004,1109.6 +20/10/2004,1101.3 +21/10/2004,1104.425 +22/10/2004,1101.45 +25/10/2004,1094.375 +26/10/2004,1102.95 +27/10/2004,1117.55 +28/10/2004,1126 +29/10/2004,1128.4 +01/11/2004,1130.4 +02/11/2004,1132.4 +03/11/2004,1137.95 +04/11/2004,1152.225 +05/11/2004,1164.8 +08/11/2004,1165.075 +09/11/2004,1165.125 +10/11/2004,1164.7 +11/11/2004,1168.525 +12/11/2004,1178.325 +15/11/2004,1183.075 +16/11/2004,1179.575 +17/11/2004,1180.3 +18/11/2004,1182.6 +19/11/2004,1176.75 +22/11/2004,1173.4 +23/11/2004,1176.25 +24/11/2004,1179.525 +26/11/2004,1183.05 +29/11/2004,1180.15 +30/11/2004,1176.225 +01/12/2004,1182.6 +02/12/2004,1190.8 +03/12/2004,1191.675 +06/12/2004,1189.75 +07/12/2004,1184.15 +08/12/2004,1180.175 +09/12/2004,1184.075 +10/12/2004,1188.475 +13/12/2004,1193.375 +14/12/2004,1201.3 +15/12/2004,1203.775 +16/12/2004,1203.825 +17/12/2004,1198.5 +20/12/2004,1196.475 +21/12/2004,1200.2 +22/12/2004,1207.575 +23/12/2004,1210.525 +27/12/2004,1208.525 +28/12/2004,1209.2 +29/12/2004,1213 +30/12/2004,1214.225 +31/12/2004,1213.6 +03/01/2005,1208.05 +04/01/2005,1195.325 +05/01/2005,1187.05 +06/01/2005,1186.6 +07/01/2005,1187.1 +10/01/2005,1189 +11/01/2005,1185.95 +12/01/2005,1183.575 +13/01/2005,1182.125 +14/01/2005,1181.175 +18/01/2005,1189.15 +19/01/2005,1190.25 +20/01/2005,1179.5 +21/01/2005,1172.65 +24/01/2005,1167.175 +25/01/2005,1167.575 +26/01/2005,1171.725 +27/01/2005,1174.075 +28/01/2005,1171.95 +31/01/2005,1176.55 +01/02/2005,1185.525 +02/02/2005,1191.675 +03/02/2005,1190.475 +04/02/2005,1196.525 +07/02/2005,1202.05 +08/02/2005,1202.325 +09/02/2005,1197.4 +10/02/2005,1194.825 +11/02/2005,1201 +14/02/2005,1205.475 +15/02/2005,1208.525 +16/02/2005,1209.475 +17/02/2005,1205.775 +18/02/2005,1200.65 +22/02/2005,1193.125 +23/02/2005,1188.175 +24/02/2005,1194.8 +25/02/2005,1205.85 +28/02/2005,1206.125 +01/03/2005,1207.45 +02/03/2005,1210.125 +03/03/2005,1210.2 +04/03/2005,1216.975 +07/03/2005,1224.65 +08/03/2005,1222.25 +09/03/2005,1213.125 +10/03/2005,1207.2 +11/03/2005,1205.125 +14/03/2005,1203.3 +15/03/2005,1203.225 +16/03/2005,1192.325 +17/03/2005,1189.475 +18/03/2005,1188.675 +21/03/2005,1185.5 +22/03/2005,1179.175 +23/03/2005,1172.3 +24/03/2005,1173.85 +28/03/2005,1174.25 +29/03/2005,1170.7 +30/03/2005,1173.425 +31/03/2005,1181.5 +01/04/2005,1178.3 +04/04/2005,1173.8 +05/04/2005,1179.3 +06/04/2005,1184.05 +07/04/2005,1187.725 +08/04/2005,1186.3 +11/04/2005,1181.3 +12/04/2005,1182.5 +13/04/2005,1180.2 +14/04/2005,1168.05 +15/04/2005,1152.125 +18/04/2005,1144.325 +19/04/2005,1149.875 +20/04/2005,1145.5 +21/04/2005,1148.75 +22/04/2005,1153.775 +25/04/2005,1157.575 +26/04/2005,1157.575 +27/04/2005,1153.1 +28/04/2005,1149.8 +29/04/2005,1149.05 +02/05/2005,1159.15 +03/05/2005,1161.75 +04/05/2005,1168.525 +05/05/2005,1173.425 +06/05/2005,1173.05 +09/05/2005,1174.6 +10/05/2005,1171.7 +11/05/2005,1166.7 +12/05/2005,1165.425 +13/05/2005,1155.85 +16/05/2005,1159.775 +17/05/2005,1168.425 +18/05/2005,1180.275 +19/05/2005,1188.075 +20/05/2005,1189.2 +23/05/2005,1192.35 +24/05/2005,1193.3 +25/05/2005,1191.05 +26/05/2005,1194.15 +27/05/2005,1197.825 +31/05/2005,1195.15 +01/06/2005,1197.6 +02/06/2005,1202.425 +03/06/2005,1199.975 +06/06/2005,1196.275 +07/06/2005,1200.225 +08/06/2005,1196.825 +09/06/2005,1197.15 +10/06/2005,1198.6 +13/06/2005,1199.85 +14/06/2005,1203.1 +15/06/2005,1204.325 +16/06/2005,1208.775 +17/06/2005,1214.575 +20/06/2005,1215.725 +21/06/2005,1214.675 +22/06/2005,1214.7 +23/06/2005,1207.95 +24/06/2005,1196.175 +27/06/2005,1191.225 +28/06/2005,1196.375 +29/06/2005,1201.05 +30/06/2005,1196.225 +01/07/2005,1193.725 +05/07/2005,1199.55 +06/07/2005,1200.2 +07/07/2005,1193.7 +08/07/2005,1204.925 +11/07/2005,1215.8 +12/07/2005,1220.925 +13/07/2005,1222.4 +14/07/2005,1226.575 +15/07/2005,1226.85 +18/07/2005,1224.5 +19/07/2005,1225.45 +20/07/2005,1231 +21/07/2005,1230.675 +22/07/2005,1230.275 +25/07/2005,1232.325 +26/07/2005,1230.9 +27/07/2005,1233.95 +28/07/2005,1240.375 +29/07/2005,1239.275 +01/08/2005,1235.6 +02/08/2005,1239.85 +03/08/2005,1243.9 +04/08/2005,1240.275 +05/08/2005,1230.95 +08/08/2005,1226.125 +09/08/2005,1227.925 +10/08/2005,1232.45 +11/08/2005,1233.25 +12/08/2005,1232.975 +15/08/2005,1231.675 +16/08/2005,1226.525 +17/08/2005,1220.8 +18/08/2005,1219.425 +19/08/2005,1220.7 +22/08/2005,1221.725 +23/08/2005,1219.175 +24/08/2005,1215.2 +25/08/2005,1211.325 +26/08/2005,1208.525 +29/08/2005,1208.3 +30/08/2005,1208.525 +31/08/2005,1213.375 +01/09/2005,1221.35 +02/09/2005,1220.475 +06/09/2005,1225.75 +07/09/2005,1234.45 +08/09/2005,1233.5 +09/09/2005,1237 +12/09/2005,1240.975 +13/09/2005,1235.9 +14/09/2005,1229.825 +15/09/2005,1227.9 +16/09/2005,1233.175 +19/09/2005,1233.625 +20/09/2005,1227.225 +21/09/2005,1215.725 +22/09/2005,1211.675 +23/09/2005,1214.625 +26/09/2005,1216.325 +27/09/2005,1215.65 +28/09/2005,1216.575 +29/09/2005,1221.2 +30/09/2005,1227.825 +03/10/2005,1228.5 +04/10/2005,1221.275 +05/10/2005,1205.4 +06/10/2005,1192.975 +07/10/2005,1194.65 +10/10/2005,1191.45 +11/10/2005,1187.125 +12/10/2005,1181.575 +13/10/2005,1175.575 +14/10/2005,1181.475 +17/10/2005,1188.1 +18/10/2005,1184.1 +19/10/2005,1185.05 +20/10/2005,1186.05 +21/10/2005,1179.7 +24/10/2005,1189.5 +25/10/2005,1196.625 +26/10/2005,1195.825 +27/10/2005,1185.475 +28/10/2005,1188.65 +31/10/2005,1203.8 +01/11/2005,1204.7 +02/11/2005,1208.475 +03/11/2005,1218.55 +04/11/2005,1219.25 +07/11/2005,1221.1 +08/11/2005,1220.075 +09/11/2005,1220.6 +10/11/2005,1224.775 +11/11/2005,1233.025 +14/11/2005,1234.375 +15/11/2005,1231.775 +16/11/2005,1229.9 +17/11/2005,1237.05 +18/11/2005,1245.35 +21/11/2005,1251.475 +22/11/2005,1257.325 +23/11/2005,1264.225 +25/11/2005,1267.025 +28/11/2005,1262.825 +29/11/2005,1259.675 +30/11/2005,1254.325 +01/12/2005,1257.475 +02/12/2005,1264.5 +05/12/2005,1262.6 +06/12/2005,1265.2 +07/12/2005,1259.725 +08/12/2005,1256.875 +09/12/2005,1258.125 +12/12/2005,1259.8 +13/12/2005,1264.625 +14/12/2005,1270.75 +15/12/2005,1271.625 +16/12/2005,1270.175 +19/12/2005,1264.25 +20/12/2005,1260.15 +21/12/2005,1262.85 +22/12/2005,1265.4 +23/12/2005,1268.125 +27/12/2005,1263.375 +28/12/2005,1258.075 +29/12/2005,1256.85 +30/12/2005,1250.925 +03/01/2006,1258.25 +04/01/2006,1271.35 +05/01/2006,1273.55 +06/01/2006,1279.65 +09/01/2006,1287.825 +10/01/2006,1288.475 +11/01/2006,1291.725 +12/01/2006,1289.875 +13/01/2006,1286.375 +17/01/2006,1284.175 +18/01/2006,1278.95 +19/01/2006,1282.15 +20/01/2006,1273.1 +23/01/2006,1263.75 +24/01/2006,1266.5 +25/01/2006,1265.725 +26/01/2006,1269.9 +27/01/2006,1279.425 +30/01/2006,1285.075 +31/01/2006,1281.825 +01/02/2006,1280.875 +02/02/2006,1275.875 +03/02/2006,1266.675 +06/02/2006,1264.4 +07/02/2006,1259.8 +08/02/2006,1260.45 +09/02/2006,1266.725 +10/02/2006,1263.925 +13/02/2006,1263.8 +14/02/2006,1269.35 +15/02/2006,1276.9 +16/02/2006,1284.7 +17/02/2006,1287.55 +21/02/2006,1285.85 +22/02/2006,1288.225 +23/02/2006,1289.85 +24/02/2006,1288.725 +27/02/2006,1292.625 +28/02/2006,1286.9 +01/03/2006,1286.1 +02/03/2006,1288.675 +03/03/2006,1289.45 +06/03/2006,1282.35 +07/03/2006,1275.9 +08/03/2006,1275.775 +09/03/2006,1276.4 +10/03/2006,1277.325 +13/03/2006,1283.675 +14/03/2006,1290.6 +15/03/2006,1299.975 +16/03/2006,1305.45 +17/03/2006,1306.9 +20/03/2006,1306.475 +21/03/2006,1302.25 +22/03/2006,1301 +23/03/2006,1302.45 +24/03/2006,1302.525 +27/03/2006,1301.85 +28/03/2006,1298.2 +29/03/2006,1298.725 +30/03/2006,1302.5 +31/03/2006,1298.2 +03/04/2006,1301.65 +04/04/2006,1301.475 +05/04/2006,1308.775 +06/04/2006,1308.75 +07/04/2006,1303.2 +10/04/2006,1296.5 +11/04/2006,1291.725 +12/04/2006,1288.025 +13/04/2006,1288.175 +17/04/2006,1286.9 +18/04/2006,1296.825 +19/04/2006,1307.7 +20/04/2006,1311.5 +21/04/2006,1311.775 +24/04/2006,1308.625 +25/04/2006,1304.95 +26/04/2006,1304.95 +27/04/2006,1306.425 +28/04/2006,1310.625 +01/05/2006,1309.125 +02/05/2006,1309.325 +03/05/2006,1309.6 +04/05/2006,1310.725 +05/05/2006,1319.175 +08/05/2006,1325.025 +09/05/2006,1324.725 +10/05/2006,1322.575 +11/05/2006,1313.65 +12/05/2006,1298.35 +15/05/2006,1291.25 +16/05/2006,1293.25 +17/05/2006,1280.25 +18/05/2006,1267.175 +19/05/2006,1264.325 +22/05/2006,1262.725 +23/05/2006,1262.15 +24/05/2006,1256.25 +25/05/2006,1265.75 +26/05/2006,1276.475 +30/05/2006,1269.9 +31/05/2006,1264.75 +01/06/2006,1277.65 +02/06/2006,1286.2 +05/06/2006,1276.6 +06/06/2006,1263.35 +07/06/2006,1262.025 +08/06/2006,1252.25 +09/06/2006,1255.7 +12/06/2006,1245.025 +13/06/2006,1231.425 +14/06/2006,1226.125 +15/06/2006,1243.7 +16/06/2006,1252.575 +19/06/2006,1246.175 +20/06/2006,1242.025 +21/06/2006,1247.6 +22/06/2006,1247.725 +23/06/2006,1246.15 +26/06/2006,1247.425 +27/06/2006,1245.5 +28/06/2006,1242.425 +29/06/2006,1259.4 +30/06/2006,1272.4 +03/07/2006,1275.2 +05/07/2006,1274.2 +06/07/2006,1273.4 +07/07/2006,1269.525 +10/07/2006,1267.85 +11/07/2006,1268.275 +12/07/2006,1265.4 +13/07/2006,1250.225 +14/07/2006,1237.425 +17/07/2006,1235.575 +18/07/2006,1233.95 +19/07/2006,1248.75 +20/07/2006,1255.15 +21/07/2006,1244.775 +24/07/2006,1250.95 +25/07/2006,1264.85 +26/07/2006,1268.275 +27/07/2006,1267.275 +28/07/2006,1271.325 +31/07/2006,1277.05 +01/08/2006,1273.45 +02/08/2006,1275.825 +03/08/2006,1278.425 +04/08/2006,1281.6 +07/08/2006,1276.85 +08/08/2006,1274.6 +09/08/2006,1271.375 +10/08/2006,1267.825 +11/08/2006,1268 +14/08/2006,1270.125 +15/08/2006,1277.05 +16/08/2006,1290.55 +17/08/2006,1296.6 +18/08/2006,1298.925 +21/08/2006,1299.4 +22/08/2006,1298.3 +23/08/2006,1295.675 +24/08/2006,1294.425 +25/08/2006,1295.575 +28/08/2006,1298.975 +29/08/2006,1301.55 +30/08/2006,1304.225 +31/08/2006,1304.15 +01/09/2006,1307.65 +05/09/2006,1311.9 +06/09/2006,1306.4 +07/09/2006,1296.875 +08/09/2006,1296.75 +11/09/2006,1297.925 +12/09/2006,1306.6 +13/09/2006,1315.45 +14/09/2006,1316.375 +15/09/2006,1319.3 +18/09/2006,1321.025 +19/09/2006,1318.425 +20/09/2006,1322.575 +21/09/2006,1321.65 +22/09/2006,1315.425 +25/09/2006,1320.525 +26/09/2006,1331.125 +27/09/2006,1336.575 +28/09/2006,1337.475 +29/09/2006,1337.625 +02/10/2006,1333.975 +03/10/2006,1332.7 +04/10/2006,1341.425 +05/10/2006,1351.15 +06/10/2006,1350.05 +09/10/2006,1349.875 +10/10/2006,1351.7 +11/10/2006,1350.225 +12/10/2006,1356.6 +13/10/2006,1363.875 +16/10/2006,1367.325 +17/10/2006,1364.725 +18/10/2006,1365.95 +19/10/2006,1365.8 +20/10/2006,1366.575 +23/10/2006,1371.725 +24/10/2006,1376.15 +25/10/2006,1379.8 +26/10/2006,1385.075 +27/10/2006,1382.725 +30/10/2006,1377.475 +31/10/2006,1377.3 +01/11/2006,1373.475 +02/11/2006,1366.325 +03/11/2006,1366.075 +06/11/2006,1372.45 +07/11/2006,1382.5 +08/11/2006,1383.275 +09/11/2006,1382.475 +10/11/2006,1378.95 +13/11/2006,1382.85 +14/11/2006,1387.8 +15/11/2006,1395.725 +16/11/2006,1399.15 +17/11/2006,1399.175 +20/11/2006,1400.975 +21/11/2006,1401.675 +22/11/2006,1404.75 +24/11/2006,1403 +27/11/2006,1391.325 +28/11/2006,1383.5 +29/11/2006,1393.2 +30/11/2006,1400.05 +01/12/2006,1396.425 +04/12/2006,1403.425 +05/12/2006,1412 +06/12/2006,1413.55 +07/12/2006,1411.325 +08/12/2006,1408.725 +11/12/2006,1411.75 +12/12/2006,1410.8 +13/12/2006,1413.025 +14/12/2006,1419.775 +15/12/2006,1427.425 +18/12/2006,1425.525 +19/12/2006,1422.775 +20/12/2006,1425.375 +21/12/2006,1420.95 +22/12/2006,1414.5 +26/12/2006,1414.025 +27/12/2006,1421.925 +28/12/2006,1425.2 +29/12/2006,1421.675 +03/01/2007,1417.975 +04/01/2007,1416.225 +05/01/2007,1413.025 +08/01/2007,1410.275 +09/01/2007,1411.475 +10/01/2007,1411.75 +11/01/2007,1420.125 +12/01/2007,1427.075 +16/01/2007,1431.275 +17/01/2007,1431.575 +18/01/2007,1428.625 +19/01/2007,1428.4 +22/01/2007,1426.325 +23/01/2007,1426 +24/01/2007,1434.05 +25/01/2007,1431.75 +26/01/2007,1422.6 +29/01/2007,1422 +30/01/2007,1424.7 +31/01/2007,1433.325 +01/02/2007,1442.075 +02/02/2007,1447.025 +05/02/2007,1447.125 +06/02/2007,1447.15 +07/02/2007,1449.2 +08/02/2007,1447.9 +09/02/2007,1443.05 +12/02/2007,1435.475 +13/02/2007,1438.775 +14/02/2007,1450.2 +15/02/2007,1455.8 +16/02/2007,1455.175 +20/02/2007,1456.225 +21/02/2007,1457.2 +22/02/2007,1456.45 +23/02/2007,1453 +26/02/2007,1450.725 +27/02/2007,1421.7 +28/02/2007,1404.5 +01/03/2007,1400.1 +02/03/2007,1395.175 +05/03/2007,1381.775 +06/03/2007,1385.375 +07/03/2007,1394.7 +08/03/2007,1398.4 +09/03/2007,1403.05 +12/03/2007,1404.275 +13/03/2007,1392.025 +14/03/2007,1379.3 +15/03/2007,1390.075 +16/03/2007,1390.1 +19/03/2007,1394.825 +20/03/2007,1406.275 +21/03/2007,1423.375 +22/03/2007,1434.275 +23/03/2007,1435.675 +26/03/2007,1433.65 +27/03/2007,1432.275 +28/03/2007,1421.975 +29/03/2007,1419.8 +30/03/2007,1420.375 +02/04/2007,1421.8 +03/04/2007,1431.75 +04/04/2007,1438.125 +05/04/2007,1441.075 +09/04/2007,1444.95 +10/04/2007,1446.425 +11/04/2007,1442.925 +12/04/2007,1442.15 +13/04/2007,1449.475 +16/04/2007,1460.675 +17/04/2007,1470.375 +18/04/2007,1471.75 +19/04/2007,1470.475 +20/04/2007,1477.6 +23/04/2007,1483.175 +24/04/2007,1479.7 +25/04/2007,1488.15 +26/04/2007,1494.675 +27/04/2007,1493.575 +30/04/2007,1489 +01/05/2007,1483.175 +02/05/2007,1491.8 +03/05/2007,1499.225 +04/05/2007,1505 +07/05/2007,1507.9 +08/05/2007,1506.8 +09/05/2007,1509.375 +10/05/2007,1501.875 +11/05/2007,1498.75 +14/05/2007,1504.55 +15/05/2007,1504.875 +16/05/2007,1507.475 +17/05/2007,1513.3 +18/05/2007,1517.75 +21/05/2007,1525.125 +22/05/2007,1525.1 +23/05/2007,1525.175 +24/05/2007,1516.025 +25/05/2007,1512.025 +29/05/2007,1516.85 +30/05/2007,1522.025 +31/05/2007,1531.175 +01/06/2007,1534.525 +04/06/2007,1537.075 +05/06/2007,1533.7 +06/06/2007,1523.175 +07/06/2007,1503.975 +08/06/2007,1498.4 +11/06/2007,1508.875 +12/06/2007,1501.6 +13/06/2007,1504.2 +14/06/2007,1520.175 +15/06/2007,1530.65 +18/06/2007,1532.15 +19/06/2007,1531.55 +20/06/2007,1524.05 +21/06/2007,1515.6 +22/06/2007,1511.925 +25/06/2007,1501.825 +26/06/2007,1496.8 +27/06/2007,1497.475 +28/06/2007,1507.55 +29/06/2007,1505.025 +02/07/2007,1512.075 +03/07/2007,1522.275 +05/07/2007,1523.65 +06/07/2007,1527.075 +09/07/2007,1531 +10/07/2007,1520.925 +11/07/2007,1513.525 +12/07/2007,1533.25 +13/07/2007,1550.025 +16/07/2007,1551.15 +17/07/2007,1550.475 +18/07/2007,1544.575 +19/07/2007,1550.125 +20/07/2007,1542.425 +23/07/2007,1539.25 +24/07/2007,1525.7 +25/07/2007,1514.275 +26/07/2007,1496.05 +27/07/2007,1472.225 +30/07/2007,1466.25 +31/07/2007,1467.925 +01/08/2007,1457.25 +02/08/2007,1468.675 +03/08/2007,1452.825 +06/08/2007,1448.95 +07/08/2007,1472.1 +08/08/2007,1488.45 +09/08/2007,1475.15 +10/08/2007,1449.6 +13/08/2007,1456.025 +14/08/2007,1440.575 +15/08/2007,1419.525 +16/08/2007,1401.125 +17/08/2007,1429.7 +20/08/2007,1443.425 +21/08/2007,1446.925 +22/08/2007,1455.75 +23/08/2007,1463.125 +24/08/2007,1470.4 +27/08/2007,1472.9 +28/08/2007,1449.45 +29/08/2007,1447.9 +30/08/2007,1460.225 +31/08/2007,1467.675 +04/09/2007,1483 +05/09/2007,1479.05 +06/09/2007,1474.85 +07/09/2007,1464.9 +10/09/2007,1451.675 +11/09/2007,1461.85 +12/09/2007,1472 +13/09/2007,1479.15 +14/09/2007,1481.85 +17/09/2007,1479.225 +18/09/2007,1498.225 +19/09/2007,1526.825 +20/09/2007,1523.25 +21/09/2007,1523.575 +24/09/2007,1522.475 +25/09/2007,1514.725 +26/09/2007,1523 +27/09/2007,1529.25 +28/09/2007,1528.425 +01/10/2007,1537.625 +02/10/2007,1545.5 +03/10/2007,1541.875 +04/10/2007,1541.075 +05/10/2007,1551.775 +08/10/2007,1553.65 +09/10/2007,1558.875 +10/10/2007,1562.1 +11/10/2007,1560.475 +12/10/2007,1558.575 +15/10/2007,1554.1 +16/10/2007,1542.6 +17/10/2007,1540.575 +18/10/2007,1538.5 +19/10/2007,1520.225 +22/10/2007,1500.65 +23/10/2007,1513.125 +24/10/2007,1509.825 +25/10/2007,1513.575 +26/10/2007,1528.3 +29/10/2007,1539.75 +30/10/2007,1534.825 +31/10/2007,1540.95 +01/11/2007,1526.675 +02/11/2007,1506.625 +05/11/2007,1502.15 +06/11/2007,1511.375 +07/11/2007,1495.4 +08/11/2007,1470.725 +09/11/2007,1460.975 +12/11/2007,1449.075 +13/11/2007,1461.25 +14/11/2007,1478.15 +15/11/2007,1458.85 +16/11/2007,1454.5 +19/11/2007,1444.275 +20/11/2007,1436.525 +21/11/2007,1425.875 +23/11/2007,1429.2 +26/11/2007,1425.025 +27/11/2007,1418.675 +28/11/2007,1451.65 +29/11/2007,1467.325 +30/11/2007,1478.175 +03/12/2007,1475.825 +04/12/2007,1466.525 +05/12/2007,1475.375 +06/12/2007,1495.525 +07/12/2007,1506.65 +10/12/2007,1511.1 +11/12/2007,1498.5 +12/12/2007,1488.6 +13/12/2007,1482.575 +14/12/2007,1477.175 +17/12/2007,1455.325 +18/12/2007,1449.2 +19/12/2007,1454.35 +20/12/2007,1456.3 +21/12/2007,1474.075 +24/12/2007,1490.775 +26/12/2007,1494.95 +27/12/2007,1485.575 +28/12/2007,1479.5 +31/12/2007,1471.125 +02/01/2008,1457.275 +03/01/2008,1448.8 +04/01/2008,1427.7 +07/01/2008,1414.425 +08/01/2008,1406.125 +09/01/2008,1396.8 +10/01/2008,1412.875 +11/01/2008,1408.9 +14/01/2008,1409.975 +15/01/2008,1396.35 +16/01/2008,1376.725 +17/01/2008,1354.1 +18/01/2008,1330.475 +22/01/2008,1304.95 +23/01/2008,1314.525 +24/01/2008,1345.425 +25/01/2008,1346 +28/01/2008,1340.25 +29/01/2008,1358.325 +30/01/2008,1364.225 +31/01/2008,1362.55 +01/02/2008,1386.475 +04/02/2008,1387.825 +05/02/2008,1358.45 +06/02/2008,1335.575 +07/02/2008,1331.225 +08/02/2008,1332.625 +11/02/2008,1333.175 +12/02/2008,1347.725 +13/02/2008,1360.075 +14/02/2008,1357.925 +15/02/2008,1346.4 +19/02/2008,1354.25 +20/02/2008,1352.15 +21/02/2008,1352.975 +22/02/2008,1344.65 +25/02/2008,1361.25 +26/02/2008,1375.925 +27/02/2008,1379.825 +28/02/2008,1371.825 +29/02/2008,1346.05 +03/03/2008,1329.225 +04/03/2008,1323.7 +05/03/2008,1331.45 +06/03/2008,1318.025 +07/03/2008,1297.625 +10/03/2008,1283.575 +11/03/2008,1297.55 +12/03/2008,1317.775 +13/03/2008,1306.15 +14/03/2008,1300.125 +17/03/2008,1276.075 +18/03/2008,1303.95 +19/03/2008,1317.325 +20/03/2008,1313.775 +24/03/2008,1342.55 +25/03/2008,1350.2 +26/03/2008,1345.625 +27/03/2008,1334.35 +28/03/2008,1322.525 +31/03/2008,1319.975 +01/04/2008,1348.3 +02/04/2008,1369.25 +03/04/2008,1367.35 +04/04/2008,1370.975 +07/04/2008,1375.475 +08/04/2008,1366.625 +09/04/2008,1359.6 +10/04/2008,1358.3 +11/04/2008,1345 +14/04/2008,1330.575 +15/04/2008,1332.025 +16/04/2008,1351.05 +17/04/2008,1363.7 +18/04/2008,1381.05 +21/04/2008,1386.325 +22/04/2008,1379.625 +23/04/2008,1379.6 +24/04/2008,1384.525 +25/04/2008,1391.2 +28/04/2008,1397.925 +29/04/2008,1392.55 +30/04/2008,1391.4 +01/05/2008,1397.125 +02/05/2008,1413 +05/05/2008,1410.1 +06/05/2008,1410.65 +07/05/2008,1405.2 +08/05/2008,1395.925 +09/05/2008,1390.55 +12/05/2008,1395.825 +13/05/2008,1402.5 +14/05/2008,1410.075 +15/05/2008,1415.825 +16/05/2008,1422.325 +19/05/2008,1428.425 +20/05/2008,1417.875 +21/05/2008,1403.175 +22/05/2008,1393.6 +23/05/2008,1383.5 +27/05/2008,1380.45 +28/05/2008,1386.675 +29/05/2008,1395.925 +30/05/2008,1400.35 +02/06/2008,1390.675 +03/06/2008,1381.825 +04/06/2008,1378.35 +05/06/2008,1390.75 +06/06/2008,1380.2 +09/06/2008,1360.95 +10/06/2008,1358.95 +11/06/2008,1346.3 +12/06/2008,1340 +13/06/2008,1350.875 +16/06/2008,1358.925 +17/06/2008,1357.175 +18/06/2008,1342.6 +19/06/2008,1339.475 +20/06/2008,1328.6 +23/06/2008,1319.225 +24/06/2008,1315.475 +25/06/2008,1321.65 +26/06/2008,1299.75 +27/06/2008,1280.875 +30/06/2008,1280.825 +01/07/2008,1276.9 +02/07/2008,1275.25 +03/07/2008,1262.35 +07/07/2008,1257.475 +08/07/2008,1260.625 +09/07/2008,1260.025 +10/07/2008,1248.275 +11/07/2008,1242.7 +14/07/2008,1237.1 +15/07/2008,1219.1 +16/07/2008,1229.25 +17/07/2008,1252.6 +18/07/2008,1258.225 +21/07/2008,1261.3 +22/07/2008,1265.075 +23/07/2008,1282.1 +24/07/2008,1267.6 +25/07/2008,1256.575 +28/07/2008,1246.675 +29/07/2008,1249.8 +30/07/2008,1274.4 +31/07/2008,1274.925 +01/08/2008,1263.675 +04/08/2008,1254.3 +05/08/2008,1269.85 +06/08/2008,1285.225 +07/08/2008,1275.85 +08/08/2008,1280.625 +11/08/2008,1301.075 +12/08/2008,1296.2 +13/08/2008,1285.825 +14/08/2008,1287.975 +15/08/2008,1296.175 +18/08/2008,1287.85 +19/08/2008,1270.8 +20/08/2008,1269.75 +21/08/2008,1273.85 +22/08/2008,1285.125 +25/08/2008,1278.175 +26/08/2008,1269.35 +27/08/2008,1277 +28/08/2008,1292.25 +29/08/2008,1289.9 +02/09/2008,1285.15 +03/09/2008,1274.45 +04/09/2008,1253.3 +05/09/2008,1234.4 +08/09/2008,1259.7 +09/09/2008,1246.425 +10/09/2008,1231.25 +11/09/2008,1234.875 +12/09/2008,1246.625 +15/09/2008,1221.8 +16/09/2008,1196.5 +17/09/2008,1183.225 +18/09/2008,1177.05 +19/09/2008,1236.6 +22/09/2008,1230.875 +23/09/2008,1201.025 +24/09/2008,1187.975 +25/09/2008,1201.25 +26/09/2008,1205.2 +29/09/2008,1157.75 +30/09/2008,1140.5 +01/10/2008,1158.275 +02/10/2008,1136.725 +03/10/2008,1116.575 +06/10/2008,1065.025 +07/10/2008,1030.725 +08/10/2008,991.475 +09/10/2008,953.175 +10/10/2008,894.425 +13/10/2008,958.975 +14/10/2008,1006.1 +15/10/2008,950.25 +16/10/2008,917.35 +17/10/2008,946.525 +20/10/2008,964.45 +21/10/2008,968.325 +22/10/2008,919 +23/10/2008,897.1 +24/10/2008,880.3 +27/10/2008,865.95 +28/10/2008,893.8 +29/10/2008,940.475 +30/10/2008,946.3 +31/10/2008,962.725 +03/11/2008,967.35 +04/11/2008,988.975 +05/11/2008,976.575 +06/11/2008,927.35 +07/11/2008,919.2 +10/11/2008,928.875 +11/11/2008,904.525 +12/11/2008,872.4 +13/11/2008,874.025 +14/11/2008,891.125 +17/11/2008,863.825 +18/11/2008,851.025 +19/11/2008,834.1 +20/11/2008,781.65 +21/11/2008,774.5 +24/11/2008,829.95 +25/11/2008,853.675 +26/11/2008,867.425 +28/11/2008,890.125 +01/12/2008,852.275 +02/12/2008,833.775 +03/12/2008,853.75 +04/12/2008,856.05 +05/12/2008,854.575 +08/12/2008,898.425 +09/12/2008,899.225 +10/12/2008,896.3 +11/12/2008,886.325 +12/12/2008,871.525 +15/12/2008,873 +16/12/2008,892.725 +17/12/2008,906.85 +18/12/2008,894.925 +19/12/2008,890.85 +22/12/2008,875.825 +23/12/2008,869.5 +24/12/2008,865.8 +26/12/2008,870.625 +29/12/2008,868.15 +30/12/2008,880.725 +31/12/2008,898.45 +02/01/2009,917.225 +05/01/2009,928.2 +06/01/2009,934.275 +07/01/2009,916 +08/01/2009,905.55 +09/01/2009,900.125 +12/01/2009,878.85 +13/01/2009,870.15 +14/01/2009,853.525 +15/01/2009,838.575 +16/01/2009,845.85 +20/01/2009,827.225 +21/01/2009,823.25 +22/01/2009,829.55 +23/01/2009,824.725 +26/01/2009,837.325 +27/01/2009,842.225 +28/01/2009,860.85 +29/01/2009,856.75 +30/01/2009,836.25 +02/02/2009,823.05 +03/02/2009,832.2 +04/02/2009,837.775 +05/02/2009,837.025 +06/02/2009,857.725 +09/02/2009,868.675 +10/02/2009,846.275 +11/02/2009,830.4 +12/02/2009,827.175 +13/02/2009,831.35 +17/02/2009,803.9 +18/02/2009,789.025 +19/02/2009,785.35 +20/02/2009,769.7 +23/02/2009,759.2 +24/02/2009,759.5 +25/02/2009,767.125 +26/02/2009,762.45 +27/02/2009,742.7 +02/03/2009,714.925 +03/03/2009,701.175 +04/03/2009,708.55 +05/03/2009,694.25 +06/03/2009,683.325 +09/03/2009,681.375 +10/03/2009,699.45 +11/03/2009,721.7 +12/03/2009,734.75 +13/03/2009,752.325 +16/03/2009,760.15 +17/03/2009,765 +18/03/2009,784.75 +19/03/2009,791.725 +20/03/2009,777.05 +23/03/2009,797.725 +24/03/2009,813.95 +25/03/2009,809.725 +26/03/2009,823.525 +27/03/2009,821.675 +30/03/2009,796.375 +31/03/2009,797.55 +01/04/2009,800.4 +02/04/2009,827.25 +03/04/2009,836.7 +06/04/2009,834.475 +07/04/2009,824.55 +08/04/2009,821.3 +09/04/2009,843.025 +13/04/2009,855.925 +14/04/2009,848.875 +15/04/2009,845 +16/04/2009,859.3 +17/04/2009,867.825 +20/04/2009,850.35 +21/04/2009,839.55 +22/04/2009,848.3 +23/04/2009,846.225 +24/04/2009,861.45 +27/04/2009,860.925 +28/04/2009,855.325 +29/04/2009,867.375 +30/04/2009,876.65 +01/05/2009,874.2 +04/05/2009,893.375 +05/05/2009,903.725 +06/05/2009,911.95 +07/05/2009,914.5 +08/05/2009,919.35 +11/05/2009,915.975 +12/05/2009,907.75 +13/05/2009,894.375 +14/05/2009,889.55 +15/05/2009,887.9 +18/05/2009,897.975 +19/05/2009,909.85 +20/05/2009,909.525 +21/05/2009,892.175 +22/05/2009,889.025 +26/05/2009,897.65 +27/05/2009,902.2 +28/05/2009,899.225 +29/05/2009,912.425 +01/06/2009,934.325 +02/06/2009,943.875 +03/06/2009,935.175 +04/06/2009,936.7 +05/06/2009,942.9 +08/06/2009,937.475 +09/06/2009,941.45 +10/06/2009,939.9 +11/06/2009,944.775 +12/06/2009,942.9 +15/06/2009,932.075 +16/06/2009,919.3 +17/06/2009,911.2 +18/06/2009,914.775 +19/06/2009,921.025 +22/06/2009,905.55 +23/06/2009,894.05 +24/06/2009,901.1 +25/06/2009,909.375 +26/06/2009,918.175 +29/06/2009,922.825 +30/06/2009,922.325 +01/07/2009,924.2 +02/07/2009,908.8 +06/07/2009,894.525 +07/07/2009,889.525 +08/07/2009,879.4 +09/07/2009,882.6 +10/07/2009,878.875 +13/07/2009,889.225 +14/07/2009,902.225 +15/07/2009,921.725 +16/07/2009,935.6 +17/07/2009,939.375 +20/07/2009,946.45 +21/07/2009,951.575 +22/07/2009,953.775 +23/07/2009,965.775 +24/07/2009,974.325 +27/07/2009,978.9 +28/07/2009,978.225 +29/07/2009,974.8 +30/07/2009,983.875 +31/07/2009,987.6 +03/08/2009,996.65 +04/08/2009,1002.7 +05/08/2009,1002.25 +06/08/2009,1000.425 +07/08/2009,1007.025 +10/08/2009,1006.775 +11/08/2009,999.6 +12/08/2009,1001.5 +13/08/2009,1008.125 +14/08/2009,1005.875 +17/08/2009,988.65 +18/08/2009,985.525 +19/08/2009,990.9 +20/08/2009,1002.275 +21/08/2009,1017.975 +24/08/2009,1027.625 +25/08/2009,1029.65 +26/08/2009,1027.375 +27/08/2009,1027.075 +28/08/2009,1030.775 +31/08/2009,1021.4 +01/09/2009,1010.575 +02/09/2009,995.8 +03/09/2009,998.725 +04/09/2009,1009.575 +08/09/2009,1022.225 +09/09/2009,1029.775 +10/09/2009,1037.3 +11/09/2009,1043.3 +14/09/2009,1043.55 +15/09/2009,1050.25 +16/09/2009,1061.125 +17/09/2009,1067.35 +18/09/2009,1067.675 +21/09/2009,1064.15 +22/09/2009,1069.525 +23/09/2009,1068.55 +24/09/2009,1056.375 +25/09/2009,1047.15 +28/09/2009,1054.725 +29/09/2009,1062.925 +30/09/2009,1057 +01/10/2009,1042.275 +02/10/2009,1026.375 +05/10/2009,1033.975 +06/10/2009,1049.8 +07/10/2009,1054.85 +08/10/2009,1064.05 +09/10/2009,1067.825 +12/10/2009,1074.725 +13/10/2009,1072.55 +14/10/2009,1085.65 +15/10/2009,1092.5 +16/10/2009,1089.65 +19/10/2009,1093.2 +20/10/2009,1093.625 +21/10/2009,1088.5 +22/10/2009,1085.85 +23/10/2009,1086.625 +26/10/2009,1076.1 +27/10/2009,1066 +28/10/2009,1052.4 +29/10/2009,1055.075 +30/10/2009,1050.1 +02/11/2009,1040.175 +03/11/2009,1041.65 +04/11/2009,1049.95 +05/11/2009,1056.975 +06/11/2009,1066.275 +09/11/2009,1082.725 +10/11/2009,1092.175 +11/11/2009,1098.425 +12/11/2009,1093.1 +13/11/2009,1091.05 +16/11/2009,1102.8 +17/11/2009,1108.05 +18/11/2009,1108.25 +19/11/2009,1099.025 +20/11/2009,1091.9 +23/11/2009,1102.1 +24/11/2009,1104.175 +25/11/2009,1108.275 +27/11/2009,1096.55 +30/11/2009,1092.525 +01/12/2009,1104.75 +02/12/2009,1109.775 +03/12/2009,1106.625 +04/12/2009,1105.5 +07/12/2009,1105.05 +08/12/2009,1096.625 +09/12/2009,1092.5 +10/12/2009,1101.475 +11/12/2009,1105.05 +14/12/2009,1111.125 +15/12/2009,1110.35 +16/12/2009,1110.5 +17/12/2009,1101.2 +18/12/2009,1099.5 +21/12/2009,1110.575 +22/12/2009,1116.825 +23/12/2009,1119.25 +24/12/2009,1123.8 +28/12/2009,1127.3 +29/12/2009,1127.8 +30/12/2009,1125.05 +31/12/2009,1121.025 +04/01/2010,1125.025 +05/01/2010,1133.875 +06/01/2010,1136.5 +07/01/2010,1137.95 +08/01/2010,1141.775 +11/01/2010,1146.175 +12/01/2010,1138.9 +13/01/2010,1141.15 +14/01/2010,1147.1 +15/01/2010,1140.725 +19/01/2010,1143.125 +20/01/2010,1140.8 +21/01/2010,1127.9 +22/01/2010,1103.25 +25/01/2010,1096.15 +26/01/2010,1095.4 +27/01/2010,1093 +28/01/2010,1090.025 +29/01/2010,1082.4 +01/02/2010,1081.6 +02/02/2010,1096.5 +03/02/2010,1098.675 +04/02/2010,1080.075 +05/02/2010,1060.475 +08/02/2010,1062.475 +09/02/2010,1067.5 +10/02/2010,1067.7 +11/02/2010,1071.55 +12/02/2010,1073.075 +16/02/2010,1087.2 +17/02/2010,1097.825 +18/02/2010,1102.875 +19/02/2010,1106.975 +22/02/2010,1108.925 +23/02/2010,1100.725 +24/02/2010,1100.75 +25/02/2010,1098.4 +26/02/2010,1103.1 +01/03/2010,1110.65 +02/03/2010,1118.825 +03/03/2010,1120.1 +04/03/2010,1120.625 +05/03/2010,1132.075 +08/03/2010,1138.675 +09/03/2010,1139.6 +10/03/2010,1143.55 +11/03/2010,1145.85 +12/03/2010,1150.525 +15/03/2010,1147.875 +16/03/2010,1155.225 +17/03/2010,1163.95 +18/03/2010,1165.225 +19/03/2010,1162.775 +22/03/2010,1160.925 +23/03/2010,1169.8 +24/03/2010,1169.85 +25/03/2010,1170.375 +26/03/2010,1167.4 +29/03/2010,1170.85 +30/03/2010,1173.45 +31/03/2010,1170.4 +01/04/2010,1175.35 +05/04/2010,1183.125 +06/04/2010,1187.5 +07/04/2010,1184.375 +08/04/2010,1182.95 +09/04/2010,1190.95 +12/04/2010,1196.325 +13/04/2010,1195.25 +14/04/2010,1204.7 +15/04/2010,1211.225 +16/04/2010,1199.825 +19/04/2010,1192.8 +20/04/2010,1203.45 +21/04/2010,1205.725 +22/04/2010,1202.925 +23/04/2010,1211.9 +26/04/2010,1215 +27/04/2010,1196.65 +28/04/2010,1188.2 +29/04/2010,1200.7 +30/04/2010,1196.95 +03/05/2010,1196.15 +04/05/2010,1184.175 +05/05/2010,1167.325 +06/05/2010,1131.5 +07/05/2010,1116.8 +10/05/2010,1142.025 +11/05/2010,1157.6 +12/05/2010,1163.85 +13/05/2010,1164.275 +14/05/2010,1144.05 +17/05/2010,1132.575 +18/05/2010,1131.375 +19/05/2010,1114.9 +20/05/2010,1089.45 +21/05/2010,1075.275 +24/05/2010,1080.3 +25/05/2010,1064.25 +26/05/2010,1074.975 +27/05/2010,1088.8 +28/05/2010,1094.85 +01/06/2010,1080.675 +02/06/2010,1085.5 +03/06/2010,1099.775 +04/06/2010,1080.55 +07/06/2010,1059.4 +08/06/2010,1054.55 +09/06/2010,1062.1 +10/06/2010,1073.05 +11/06/2010,1085.9 +14/06/2010,1094.875 +15/06/2010,1103.3 +16/06/2010,1113.6 +17/06/2010,1113.9 +18/06/2010,1117.15 +21/06/2010,1118.85 +22/06/2010,1105.475 +23/06/2010,1093.125 +24/06/2010,1081.775 +25/06/2010,1075.85 +28/06/2010,1076.55 +29/06/2010,1054.65 +30/06/2010,1036.925 +01/07/2010,1025.75 +02/07/2010,1024.8 +06/07/2010,1029.275 +07/07/2010,1044.55 +08/07/2010,1065.625 +09/07/2010,1073.7 +12/07/2010,1076.825 +13/07/2010,1089.05 +14/07/2010,1094.4 +15/07/2010,1092.55 +16/07/2010,1078.95 +19/07/2010,1068.45 +20/07/2010,1072.2 +21/07/2010,1077.625 +22/07/2010,1083.85 +23/07/2010,1096.625 +26/07/2010,1108.55 +27/07/2010,1115.5 +28/07/2010,1109.175 +29/07/2010,1104.575 +30/07/2010,1098.6 +02/08/2010,1117.05 +03/08/2010,1122 +04/08/2010,1124.15 +05/08/2010,1124.25 +06/08/2010,1118.5 +09/08/2010,1125.175 +10/08/2010,1120.7 +11/08/2010,1102.95 +12/08/2010,1082.125 +13/08/2010,1081.65 +16/08/2010,1077.25 +17/08/2010,1088.75 +18/08/2010,1092.975 +19/08/2010,1082.775 +20/08/2010,1071.7 +23/08/2010,1072.375 +24/08/2010,1056.25 +25/08/2010,1050.875 +26/08/2010,1052.6 +27/08/2010,1054.7 +30/08/2010,1056.25 +31/08/2010,1048.05 +01/09/2010,1065.25 +02/09/2010,1085.325 +03/09/2010,1099.2 +07/09/2010,1097.05 +08/09/2010,1096.75 +09/09/2010,1104.225 +10/09/2010,1107.225 +13/09/2010,1118.15 +14/09/2010,1121.325 +15/09/2010,1121.4 +16/09/2010,1123.225 +17/09/2010,1126.475 +20/09/2010,1135.2 +21/09/2010,1141.85 +22/09/2010,1137.45 +23/09/2010,1128.875 +24/09/2010,1140.25 +27/09/2010,1145.675 +28/09/2010,1143.025 +29/09/2010,1145.1 +30/09/2010,1145.125 +01/10/2010,1144.85 +04/10/2010,1140.525 +05/10/2010,1151.25 +06/10/2010,1159.225 +07/10/2010,1158.75 +08/10/2010,1161.725 +11/10/2010,1165.325 +12/10/2010,1165.6 +13/10/2010,1176.275 +14/10/2010,1174.3 +15/10/2010,1175.5 +18/10/2010,1180.375 +19/10/2010,1170.7 +20/10/2010,1173.625 +21/10/2010,1180.175 +22/10/2010,1181.625 +25/10/2010,1187.775 +26/10/2010,1183.825 +27/10/2010,1180.45 +28/10/2010,1183.725 +29/10/2010,1183.1 +01/11/2010,1185.9 +02/11/2010,1191.325 +03/11/2010,1193.425 +04/11/2010,1209.725 +05/11/2010,1223.6 +08/11/2010,1222.125 +09/11/2010,1218.175 +10/11/2010,1213.725 +11/11/2010,1211.625 +12/11/2010,1203.225 +15/11/2010,1200.7 +16/11/2010,1185.225 +17/11/2010,1179.075 +18/11/2010,1191.15 +19/11/2010,1196.3 +22/11/2010,1194.85 +23/11/2010,1185.65 +24/11/2010,1191.075 +26/11/2010,1191.175 +29/11/2010,1185.2 +30/11/2010,1181.25 +01/12/2010,1196.725 +02/12/2010,1214.25 +03/12/2010,1221.75 +06/12/2010,1223.375 +07/12/2010,1227.3 +08/12/2010,1225.425 +09/12/2010,1231.15 +10/12/2010,1236.8 +13/12/2010,1242.5 +14/12/2010,1242.05 +15/12/2010,1238.75 +16/12/2010,1238.95 +17/12/2010,1243.3 +20/12/2010,1246.15 +21/12/2010,1252.3 +22/12/2010,1257 +23/12/2010,1256.725 +27/12/2010,1255.525 +28/12/2010,1258.425 +29/12/2010,1260 +30/12/2010,1258.675 +31/12/2010,1256.975 +03/01/2011,1265.825 +04/01/2011,1270 +05/01/2011,1272.1 +06/01/2011,1274.675 +07/01/2011,1271.1 +10/01/2011,1268.575 +11/01/2011,1273.475 +12/01/2011,1281.075 +13/01/2011,1284.2 +14/01/2011,1287.625 +18/01/2011,1293.625 +19/01/2011,1287.475 +20/01/2011,1278.925 +21/01/2011,1285.05 +24/01/2011,1287.125 +25/01/2011,1287.95 +26/01/2011,1295.075 +27/01/2011,1298.175 +28/01/2011,1288.425 +31/01/2011,1281.575 +01/02/2011,1298.675 +02/02/2011,1305.025 +03/02/2011,1303.325 +04/02/2011,1307.65 +07/02/2011,1316.35 +08/02/2011,1321.075 +09/02/2011,1320.7 +10/02/2011,1318.625 +11/02/2011,1323.7 +14/02/2011,1330.225 +15/02/2011,1328.35 +16/02/2011,1333.225 +17/02/2011,1336.825 +18/02/2011,1341.4 +22/02/2011,1326.375 +23/02/2011,1310.05 +24/02/2011,1304.6 +25/02/2011,1313.775 +28/02/2011,1324.675 +01/03/2011,1318.275 +02/03/2011,1307.675 +03/03/2011,1322.025 +04/03/2011,1323.9 +07/03/2011,1316.125 +08/03/2011,1316.35 +09/03/2011,1318.85 +10/03/2011,1305.175 +11/03/2011,1299.5 +14/03/2011,1296.3 +15/03/2011,1280 +16/03/2011,1266.575 +17/03/2011,1268.95 +18/03/2011,1280.25 +21/03/2011,1290.6 +22/03/2011,1296.025 +23/03/2011,1293.55 +24/03/2011,1304.825 +25/03/2011,1313.75 +28/03/2011,1313.9 +29/03/2011,1313.4 +30/03/2011,1325.95 +31/03/2011,1327 +01/04/2011,1332.15 +04/04/2011,1333.075 +05/04/2011,1333.2 +06/04/2011,1335.475 +07/04/2011,1333.425 +08/04/2011,1331.7 +11/04/2011,1327.1 +12/04/2011,1316.925 +13/04/2011,1314.725 +14/04/2011,1311.2 +15/04/2011,1317.7 +18/04/2011,1306.6 +19/04/2011,1308.825 +20/04/2011,1325.325 +21/04/2011,1335.225 +25/04/2011,1335.325 +26/04/2011,1342.575 +27/04/2011,1351.45 +28/04/2011,1357.425 +29/04/2011,1361.75 +02/05/2011,1363.9 +03/05/2011,1356.675 +04/05/2011,1350.15 +05/05/2011,1339.125 +06/05/2011,1342.6 +09/05/2011,1343.625 +10/05/2011,1353.3 +11/05/2011,1346.875 +12/05/2011,1342.775 +13/05/2011,1342.6 +16/05/2011,1333.725 +17/05/2011,1326 +18/05/2011,1334.4 +19/05/2011,1342.3 +20/05/2011,1337 +23/05/2011,1324.125 +24/05/2011,1317.9 +25/05/2011,1318.65 +26/05/2011,1322.3 +27/05/2011,1329.275 +31/05/2011,1338.15 +01/06/2011,1329.65 +02/06/2011,1312.75 +03/06/2011,1305.975 +06/06/2011,1292.875 +07/06/2011,1288.025 +08/06/2011,1282.15 +09/06/2011,1285.675 +10/06/2011,1279.125 +13/06/2011,1271.425 +14/06/2011,1281.2 +15/06/2011,1275.775 +16/06/2011,1266.325 +17/06/2011,1271.825 +20/06/2011,1274.475 +21/06/2011,1287.475 +22/06/2011,1292 +23/06/2011,1279.9 +24/06/2011,1275.65 +27/06/2011,1275.225 +28/06/2011,1288.475 +29/06/2011,1302.55 +30/06/2011,1314.45 +01/07/2011,1329.875 +05/07/2011,1338.175 +06/07/2011,1337.15 +07/07/2011,1347.225 +08/07/2011,1345.575 +11/07/2011,1330.625 +12/07/2011,1318.425 +13/07/2011,1319.55 +14/07/2011,1315 +15/07/2011,1312.55 +18/07/2011,1308.275 +19/07/2011,1317.25 +20/07/2011,1327.15 +21/07/2011,1335.55 +22/07/2011,1342.975 +25/07/2011,1339.275 +26/07/2011,1334.35 +27/07/2011,1318.05 +28/07/2011,1305.25 +29/07/2011,1294.875 +01/08/2011,1290.4 +02/08/2011,1270.3 +03/08/2011,1252.575 +04/08/2011,1230 +05/08/2011,1196.475 +08/08/2011,1158.95 +09/08/2011,1141.775 +10/08/2011,1145.6 +11/08/2011,1150.375 +12/08/2011,1177.85 +15/08/2011,1191.7 +16/08/2011,1195.425 +17/08/2011,1194.925 +18/08/2011,1162.725 +19/08/2011,1135.125 +22/08/2011,1128.475 +23/08/2011,1142.975 +24/08/2011,1168.675 +25/08/2011,1170.55 +26/08/2011,1163.175 +29/08/2011,1194.05 +30/08/2011,1209.65 +31/08/2011,1217.975 +01/09/2011,1214.15 +02/09/2011,1188.1 +06/09/2011,1163.325 +07/09/2011,1182.2 +08/09/2011,1192.9 +09/09/2011,1168.35 +12/09/2011,1153.6 +13/09/2011,1167.325 +14/09/2011,1181.775 +15/09/2011,1199.25 +16/09/2011,1212.45 +19/09/2011,1205.625 +20/09/2011,1207.075 +21/09/2011,1185.725 +22/09/2011,1143.2 +23/09/2011,1132.075 +26/09/2011,1148.8 +27/09/2011,1174.475 +28/09/2011,1165.4 +29/09/2011,1156.975 +30/09/2011,1145.625 +03/10/2011,1117.075 +04/10/2011,1105.325 +05/10/2011,1132.45 +06/10/2011,1152.4 +07/10/2011,1160.55 +10/10/2011,1176.55 +11/10/2011,1194.15 +12/10/2011,1204.95 +13/10/2011,1202.2 +14/10/2011,1215.15 +17/10/2011,1212.1 +18/10/2011,1212.7 +19/10/2011,1217.325 +20/10/2011,1210.825 +21/10/2011,1227 +24/10/2011,1247.025 +25/10/2011,1241.05 +26/10/2011,1234.65 +27/10/2011,1266.325 +28/10/2011,1283.4 +31/10/2011,1269.125 +01/11/2011,1233.925 +02/11/2011,1229.9 +03/11/2011,1249.35 +04/11/2011,1253.425 +07/11/2011,1254.2 +08/11/2011,1267.375 +09/11/2011,1251.525 +10/11/2011,1235.8 +11/11/2011,1252.75 +14/11/2011,1256.525 +15/11/2011,1254.5 +16/11/2011,1247.5 +17/11/2011,1224.95 +18/11/2011,1216.7 +21/11/2011,1201.85 +22/11/2011,1189.875 +23/11/2011,1174.65 +25/11/2011,1162.875 +28/11/2011,1176.8 +29/11/2011,1195.825 +30/11/2011,1221.875 +01/12/2011,1245.575 +02/12/2011,1248.425 +05/12/2011,1253.1 +06/12/2011,1258.675 +07/12/2011,1257.75 +08/12/2011,1246.9 +09/12/2011,1245.6 +12/12/2011,1243.425 +13/12/2011,1232.95 +14/12/2011,1218.175 +15/12/2011,1216.4 +16/12/2011,1220.5 +19/12/2011,1213 +20/12/2011,1223.875 +21/12/2011,1239.875 +22/12/2011,1249.15 +23/12/2011,1259.675 +27/12/2011,1265.525 +28/12/2011,1257.35 +29/12/2011,1256.525 +30/12/2011,1260.5 +03/01/2012,1269.875 +04/01/2012,1275.275 +05/01/2012,1276.675 +06/01/2012,1278.45 +09/01/2012,1278.75 +10/01/2012,1287.55 +11/01/2012,1290.925 +12/01/2012,1292.65 +13/01/2012,1289.075 +17/01/2012,1294.275 +18/01/2012,1300.2 +19/01/2012,1311.55 +20/01/2012,1313.625 +23/01/2012,1315.875 +24/01/2012,1313.2 +25/01/2012,1319.1 +26/01/2012,1322.95 +27/01/2012,1316.575 +30/01/2012,1311.475 +31/01/2012,1313.5 +01/02/2012,1319.9 +02/02/2012,1325.125 +03/02/2012,1335.65 +06/02/2012,1342.625 +07/02/2012,1344.1 +08/02/2012,1347.5 +09/02/2012,1350.225 +10/02/2012,1345.575 +13/02/2012,1347.825 +14/02/2012,1348.475 +15/02/2012,1347.6 +16/02/2012,1350.2 +17/02/2012,1359.975 +21/02/2012,1362.325 +22/02/2012,1359.5 +23/02/2012,1359.375 +24/02/2012,1365.4 +27/02/2012,1364.9 +28/02/2012,1369.725 +29/02/2012,1369.925 +01/03/2012,1370.525 +02/03/2012,1371.15 +05/03/2012,1365.65 +06/03/2012,1352.65 +07/03/2012,1348.55 +08/03/2012,1360 +09/03/2012,1369.425 +12/03/2012,1370.4 +13/03/2012,1383.975 +14/03/2012,1394.925 +15/03/2012,1398.05 +16/03/2012,1403.525 +19/03/2012,1407.6 +20/03/2012,1405.6 +21/03/2012,1404.2 +22/03/2012,1396.825 +23/03/2012,1394 +26/03/2012,1406.825 +27/03/2012,1415.05 +28/03/2012,1407.225 +29/03/2012,1401.425 +30/03/2012,1406.025 +02/04/2012,1413.6 +03/04/2012,1414 +04/04/2012,1404.825 +05/04/2012,1397.85 +09/04/2012,1388.85 +10/04/2012,1370.3 +11/04/2012,1365.35 +12/04/2012,1378.325 +13/04/2012,1378.825 +16/04/2012,1371.25 +17/04/2012,1380.7 +18/04/2012,1387.5 +19/04/2012,1380.7 +20/04/2012,1379.975 +23/04/2012,1370.675 +24/04/2012,1370.35 +25/04/2012,1381.575 +26/04/2012,1395 +27/04/2012,1401.875 +30/04/2012,1399.625 +01/05/2012,1403.675 +02/05/2012,1401.8 +03/05/2012,1396.425 +04/05/2012,1380.025 +07/05/2012,1369.05 +08/05/2012,1362.475 +09/05/2012,1356.15 +10/05/2012,1358.275 +11/05/2012,1356.525 +14/05/2012,1344.675 +15/05/2012,1335.6 +16/05/2012,1330.55 +17/05/2012,1315.25 +18/05/2012,1301.1 +21/05/2012,1305.95 +22/05/2012,1317.8 +23/05/2012,1313.025 +24/05/2012,1318.5 +25/05/2012,1319.25 +29/05/2012,1326.275 +30/05/2012,1321.625 +31/05/2012,1310.5 +01/06/2012,1293.75 +04/06/2012,1276.425 +05/06/2012,1281.275 +06/06/2012,1300.35 +07/06/2012,1318.225 +08/06/2012,1318.575 +11/06/2012,1319.45 +12/06/2012,1316.125 +13/06/2012,1319.175 +14/06/2012,1322.95 +15/06/2012,1336.125 +18/06/2012,1342.475 +19/06/2012,1352.775 +20/06/2012,1355.45 +21/06/2012,1340.9 +22/06/2012,1331.15 +25/06/2012,1323.2 +26/06/2012,1317.15 +27/06/2012,1326.9 +28/06/2012,1326.325 +29/06/2012,1346.15 +02/07/2012,1362.45 +03/07/2012,1369.525 +05/07/2012,1369.525 +06/07/2012,1359.225 +09/07/2012,1352.2 +10/07/2012,1348.075 +11/07/2012,1340.275 +12/07/2012,1335.7 +13/07/2012,1346.025 +16/07/2012,1353.975 +17/07/2012,1356.975 +18/07/2012,1367.675 +19/07/2012,1375.275 +20/07/2012,1369.475 +23/07/2012,1353.175 +24/07/2012,1342.375 +25/07/2012,1337.925 +26/07/2012,1349.875 +27/07/2012,1373.8 +30/07/2012,1386.075 +31/07/2012,1382.75 +01/08/2012,1378.175 +02/08/2012,1367.475 +03/08/2012,1379.05 +06/08/2012,1393.95 +07/08/2012,1399.35 +08/08/2012,1400.9 +09/08/2012,1402.475 +10/08/2012,1402.525 +13/08/2012,1403.3 +14/08/2012,1404.725 +15/08/2012,1404.725 +16/08/2012,1410.925 +17/08/2012,1416.85 +20/08/2012,1416.525 +21/08/2012,1417.225 +22/08/2012,1412.375 +23/08/2012,1407.4 +24/08/2012,1406.15 +27/08/2012,1411.7 +28/08/2012,1409.725 +29/08/2012,1410.1 +30/08/2012,1404.175 +31/08/2012,1404.7 +04/09/2012,1404.325 +05/09/2012,1404.575 +06/09/2012,1417.75 +07/09/2012,1434.85 +10/09/2012,1433.675 +11/09/2012,1432.4 +12/09/2012,1435.6 +13/09/2012,1448.925 +14/09/2012,1465.125 +17/09/2012,1462.425 +18/09/2012,1459.525 +19/09/2012,1460.9 +20/09/2012,1458.125 +21/09/2012,1461.775 +24/09/2012,1457.375 +25/09/2012,1450.825 +26/09/2012,1436.75 +27/09/2012,1441.05 +28/09/2012,1442.625 +01/10/2012,1445.85 +02/10/2012,1445.325 +03/10/2012,1448.325 +04/10/2012,1456.675 +05/10/2012,1462.55 +08/10/2012,1457.7 +09/10/2012,1448.625 +10/10/2012,1436.8 +11/10/2012,1435.575 +12/10/2012,1431.325 +15/10/2012,1434.35 +16/10/2012,1447.75 +17/10/2012,1457.65 +18/10/2012,1458.7 +19/10/2012,1444.4 +22/10/2012,1431.15 +23/10/2012,1422.025 +24/10/2012,1412.275 +25/10/2012,1412.225 +26/10/2012,1411.325 +31/10/2012,1412 +01/11/2012,1420.075 +02/11/2012,1422.25 +05/11/2012,1414.825 +06/11/2012,1424.1 +07/11/2012,1409.8 +08/11/2012,1387.675 +09/11/2012,1380.425 +12/11/2012,1380.5 +13/11/2012,1378.675 +14/11/2012,1365.675 +15/11/2012,1354.325 +16/11/2012,1354.65 +19/11/2012,1373.4 +20/11/2012,1385.35 +21/11/2012,1389.1 +23/11/2012,1400.1 +26/11/2012,1405.6 +27/11/2012,1403.05 +28/11/2012,1401.1 +29/11/2012,1413.675 +30/11/2012,1415.675 +03/12/2012,1414.5 +04/12/2012,1408.325 +05/12/2012,1407.525 +06/12/2012,1410.8 +07/12/2012,1415.825 +10/12/2012,1418.45 +11/12/2012,1424.775 +12/12/2012,1430.425 +13/12/2012,1423.85 +14/12/2012,1416.125 +17/12/2012,1422.025 +18/12/2012,1438.95 +19/12/2012,1441.55 +20/12/2012,1439 +21/12/2012,1435.05 +24/12/2012,1427.95 +26/12/2012,1423.075 +27/12/2012,1415.625 +28/12/2012,1410.05 +31/12/2012,1413.35 +02/01/2013,1444.3 +03/01/2013,1460.7 +04/01/2013,1463.2 +07/01/2013,1462.875 +08/01/2013,1458.15 +09/01/2013,1460.025 +10/01/2013,1467.5 +11/01/2013,1471.125 +14/01/2013,1470.1 +15/01/2013,1470.025 +16/01/2013,1471.625 +17/01/2013,1477.825 +18/01/2013,1482.2 +22/01/2013,1488.1 +23/01/2013,1493.35 +24/01/2013,1495.35 +25/01/2013,1498.975 +28/01/2013,1500.675 +29/01/2013,1503.85 +30/01/2013,1504.95 +31/01/2013,1500.275 +01/02/2013,1505.95 +04/02/2013,1504.275 +05/02/2013,1504.425 +06/02/2013,1510.15 +07/02/2013,1508.225 +08/02/2013,1513.75 +11/02/2013,1516.7 +12/02/2013,1518.575 +13/02/2013,1520.075 +14/02/2013,1519.7 +15/02/2013,1519.875 +19/02/2013,1525.35 +20/02/2013,1521.3 +21/02/2013,1505.925 +22/02/2013,1509 +25/02/2013,1504.25 +26/02/2013,1492.175 +27/02/2013,1506.975 +28/02/2013,1517.625 +01/03/2013,1513.6 +04/03/2013,1520.25 +05/03/2013,1533.425 +06/03/2013,1541.15 +07/03/2013,1543.275 +08/03/2013,1547.725 +11/03/2013,1552.775 +12/03/2013,1553.425 +13/03/2013,1552.9 +14/03/2013,1558.875 +15/03/2013,1560.8 +18/03/2013,1554.65 +19/03/2013,1549.05 +20/03/2013,1554.225 +21/03/2013,1551.675 +22/03/2013,1551.6 +25/03/2013,1554.925 +26/03/2013,1557.8 +27/03/2013,1560.65 +28/03/2013,1565.875 +01/04/2013,1565.125 +02/04/2013,1567.075 +03/04/2013,1561.3 +04/04/2013,1557.2 +05/04/2013,1553.2 +08/04/2013,1557.025 +09/04/2013,1566.625 +10/04/2013,1578.5 +11/04/2013,1591.15 +12/04/2013,1588.85 +15/04/2013,1570.575 +16/04/2013,1563.675 +17/04/2013,1561.225 +18/04/2013,1546 +19/04/2013,1548.025 +22/04/2013,1557.85 +23/04/2013,1570.85 +24/04/2013,1579.1 +25/04/2013,1583.9 +26/04/2013,1582.7 +29/04/2013,1588.725 +30/04/2013,1593.825 +01/05/2013,1589.75 +02/05/2013,1590.45 +03/05/2013,1607.025 +06/05/2013,1616.475 +07/05/2013,1621.525 +08/05/2013,1628.55 +09/05/2013,1629.375 +10/05/2013,1629.45 +13/05/2013,1632.15 +14/05/2013,1642.25 +15/05/2013,1654.025 +16/05/2013,1654.425 +17/05/2013,1660 +20/05/2013,1667.075 +21/05/2013,1668.25 +22/05/2013,1665.2 +23/05/2013,1648.275 +24/05/2013,1645.75 +28/05/2013,1659.875 +29/05/2013,1650.4 +30/05/2013,1653.5 +31/05/2013,1643.125 +03/06/2013,1633.8 +04/06/2013,1635.55 +05/06/2013,1618.575 +06/06/2013,1613.175 +07/06/2013,1634.6 +10/06/2013,1643.875 +11/06/2013,1631.925 +12/06/2013,1622.75 +13/06/2013,1623.975 +14/06/2013,1631.75 +17/06/2013,1636.6 +18/06/2013,1646.4 +19/06/2013,1640.525 +20/06/2013,1605.425 +21/06/2013,1589.475 +24/06/2013,1577.75 +25/06/2013,1584.1 +26/06/2013,1598.675 +27/06/2013,1611.525 +28/06/2013,1608.6 +01/07/2013,1615.3 +02/07/2013,1614.875 +03/07/2013,1612.625 +05/07/2013,1624.35 +08/07/2013,1638.4 +09/07/2013,1648.075 +10/07/2013,1652.45 +11/07/2013,1666.6 +12/07/2013,1677 +15/07/2013,1681.125 +16/07/2013,1678.625 +17/07/2013,1680.375 +18/07/2013,1686.125 +19/07/2013,1688.625 +22/07/2013,1694.55 +23/07/2013,1694.725 +24/07/2013,1690.75 +25/07/2013,1686.6 +26/07/2013,1686.7 +29/07/2013,1687.1 +30/07/2013,1687.375 +31/07/2013,1689.2 +01/08/2013,1698.375 +02/08/2013,1706.55 +05/08/2013,1706.95 +06/08/2013,1700.575 +07/08/2013,1691.6 +08/08/2013,1694.85 +09/08/2013,1693.225 +12/08/2013,1688.175 +13/08/2013,1691.075 +14/08/2013,1689.9 +15/08/2013,1669.775 +16/08/2013,1658.3 +19/08/2013,1651.575 +20/08/2013,1651.025 +21/08/2013,1647.475 +22/08/2013,1651.625 +23/08/2013,1660.75 +26/08/2013,1661.65 +27/08/2013,1641.125 +28/08/2013,1633.475 +29/08/2013,1637.25 +30/08/2013,1635 +03/09/2013,1640.125 +04/09/2013,1646.725 +05/09/2013,1655.175 +06/09/2013,1654.5 +09/09/2013,1664.425 +10/09/2013,1679.175 +11/09/2013,1684.475 +12/09/2013,1686.15 +13/09/2013,1685.975 +16/09/2013,1696.5 +17/09/2013,1701.425 +18/09/2013,1715.225 +19/09/2013,1724.925 +20/09/2013,1716.6 +23/09/2013,1705.425 +24/09/2013,1700.625 +25/09/2013,1696.1 +26/09/2013,1697.4 +27/09/2013,1692.475 +30/09/2013,1682.775 +01/10/2013,1689 +02/10/2013,1690 +03/10/2013,1683.425 +04/10/2013,1684.625 +07/10/2013,1681.3 +08/10/2013,1665.875 +09/10/2013,1655.6 +10/10/2013,1676.75 +11/10/2013,1696.55 +14/10/2013,1703.275 +15/10/2013,1703.7 +16/10/2013,1711.075 +17/10/2013,1725.25 +18/10/2013,1740.55 +21/10/2013,1744.6 +22/10/2013,1751.75 +23/10/2013,1747.875 +24/10/2013,1749.75 +25/10/2013,1757.025 +28/10/2013,1761.05 +29/10/2013,1767.475 +30/10/2013,1767 +31/10/2013,1760.975 +01/11/2013,1759.675 +04/11/2013,1765.425 +05/11/2013,1762.875 +06/11/2013,1768.4 +07/11/2013,1759.65 +08/11/2013,1759.35 +11/11/2013,1770.775 +12/11/2013,1767.825 +13/11/2013,1772.25 +14/11/2013,1786.275 +15/11/2013,1794.45 +18/11/2013,1795.15 +19/11/2013,1789.725 +20/11/2013,1785.975 +21/11/2013,1790 +22/11/2013,1800.375 +25/11/2013,1804.375 +26/11/2013,1803.725 +27/11/2013,1805.45 +29/11/2013,1808 +02/12/2013,1804 +03/12/2013,1795.8 +04/12/2013,1791.225 +05/12/2013,1788.5 +06/12/2013,1796.975 +09/12/2013,1808.075 +10/12/2013,1805.125 +11/12/2013,1792.025 +12/12/2013,1778.125 +13/12/2013,1776.675 +16/12/2013,1783.425 +17/12/2013,1782.825 +18/12/2013,1792.825 +19/12/2013,1807.7 +20/12/2013,1815.675 +23/12/2013,1825.9 +24/12/2013,1830.65 +26/12/2013,1838.7 +27/12/2013,1842.275 +30/12/2013,1840.975 +31/12/2013,1845.7 +02/01/2014,1837.875 +03/01/2014,1832.975 +06/01/2014,1830 +07/01/2014,1833.85 +08/01/2014,1836.7 +09/01/2014,1837.675 +10/01/2014,1839.525 +13/01/2014,1829.875 +14/01/2014,1830.25 +15/01/2014,1845.05 +16/01/2014,1845.55 +17/01/2014,1841.025 +21/01/2014,1841.625 +22/01/2014,1844.35 +23/01/2014,1833.3 +24/01/2014,1808.65 +27/01/2014,1785.375 +28/01/2014,1787.225 +29/01/2014,1781.275 +30/01/2014,1786.85 +31/01/2014,1784.925 +03/02/2014,1762.275 +04/02/2014,1750.375 +05/02/2014,1749.675 +06/02/2014,1763.375 +07/02/2014,1786.75 +10/02/2014,1796.925 +11/02/2014,1811.05 +12/02/2014,1820.475 +13/02/2014,1821 +14/02/2014,1833.6 +18/02/2014,1839.425 +19/02/2014,1835.55 +20/02/2014,1834.1 +21/02/2014,1839.75 +24/02/2014,1844.975 +25/02/2014,1846.475 +26/02/2014,1846.1 +27/02/2014,1848.7 +28/02/2014,1857.55 +03/03/2014,1848.875 +04/03/2014,1862.125 +05/03/2014,1873.85 +06/03/2014,1876.825 +07/03/2014,1877.675 +10/03/2014,1875 +11/03/2014,1873.025 +12/03/2014,1864.3 +13/03/2014,1857.925 +14/03/2014,1844.55 +17/03/2014,1851.675 +18/03/2014,1865.95 +19/03/2014,1864.35 +20/03/2014,1865.05 +21/03/2014,1872.125 +24/03/2014,1862.025 +25/03/2014,1863.25 +26/03/2014,1862.05 +27/03/2014,1849.675 +28/03/2014,1856.1 +31/03/2014,1866.475 +01/04/2014,1879.825 +02/04/2014,1888.625 +03/04/2014,1889.175 +04/04/2014,1878.975 +07/04/2014,1853.6 +08/04/2014,1847.5 +09/04/2014,1862.4 +10/04/2014,1852.2 +11/04/2014,1823.975 +14/04/2014,1824.7 +15/04/2014,1833.7 +16/04/2014,1854.15 +17/04/2014,1863.2 +21/04/2014,1868.2 +22/04/2014,1877.4 +23/04/2014,1877.1 +24/04/2014,1878.725 +25/04/2014,1869.625 +28/04/2014,1865.5 +29/04/2014,1875.125 +30/04/2014,1879.75 +01/05/2014,1883.675 +02/05/2014,1884.05 +05/05/2014,1879.125 +06/05/2014,1875.7 +07/05/2014,1871.325 +08/05/2014,1878.025 +09/05/2014,1874.85 +12/05/2014,1888.45 +13/05/2014,1898.15 +14/05/2014,1892.125 +15/05/2014,1877.4 +16/05/2014,1873.05 +19/05/2014,1880.05 +20/05/2014,1877.675 +21/05/2014,1880.85 +22/05/2014,1890.6 +23/05/2014,1897.1 +27/05/2014,1907.05 +28/05/2014,1910.85 +29/05/2014,1915.1 +30/05/2014,1921.125 +02/06/2014,1922.7 +03/06/2014,1922.8 +04/06/2014,1924.55 +05/06/2014,1933.4 +06/06/2014,1945.9 +09/06/2014,1950.75 +10/06/2014,1949.15 +11/06/2014,1945.7 +12/06/2014,1935.625 +13/06/2014,1933 +16/06/2014,1936.175 +17/06/2014,1939.1 +18/06/2014,1949.175 +19/06/2014,1957.3 +20/06/2014,1961.625 +23/06/2014,1962.025 +24/06/2014,1957.125 +25/06/2014,1954.275 +26/06/2014,1955.425 +27/06/2014,1957.825 +30/06/2014,1960.85 +01/07/2014,1969.125 +02/07/2014,1974.25 +03/07/2014,1980.7 +07/07/2014,1980.25 +08/07/2014,1969 +09/07/2014,1969.3 +10/07/2014,1963.525 +11/07/2014,1965.425 +14/07/2014,1974.175 +15/07/2014,1974.625 +16/07/2014,1979.375 +17/07/2014,1968.825 +18/07/2014,1970.1 +21/07/2014,1973.3 +22/07/2014,1980.275 +23/07/2014,1985.975 +24/07/2014,1988.325 +25/07/2014,1980.475 +28/07/2014,1976.475 +29/07/2014,1976.2 +30/07/2014,1971.15 +31/07/2014,1947.9 +01/08/2014,1927.175 +04/08/2014,1932.425 +05/08/2014,1926.65 +06/08/2014,1919.225 +07/08/2014,1916.575 +08/08/2014,1920.825 +11/08/2014,1937.15 +12/08/2014,1934.375 +13/08/2014,1941.575 +14/08/2014,1951.3 +15/08/2014,1954.875 +18/08/2014,1965.125 +19/08/2014,1977.4 +20/08/2014,1983.325 +21/08/2014,1990.2 +22/08/2014,1989.825 +25/08/2014,1995.825 +26/08/2014,2000.55 +27/08/2014,1999.725 +28/08/2014,1995.775 +29/08/2014,2000 +02/09/2014,2001.825 +03/09/2014,2002.925 +04/09/2014,2000.775 +05/09/2014,2000.875 +08/09/2014,2002.875 +09/09/2014,1993.675 +10/09/2014,1990.95 +11/09/2014,1993.475 +12/09/2014,1989.8 +15/09/2014,1983.95 +16/09/2014,1990.575 +17/09/2014,2001.225 +18/09/2014,2007.475 +19/09/2014,2012.25 +22/09/2014,2000.875 +23/09/2014,1988.45 +24/09/2014,1990 +25/09/2014,1981.65 +26/09/2014,1975.4 +29/09/2014,1975.525 +30/09/2014,1976.175 +01/10/2014,1957.675 +02/10/2014,1942.575 +03/10/2014,1958.825 +06/10/2014,1967.75 +07/10/2014,1948.7 +08/10/2014,1950 +09/10/2014,1947.8 +10/10/2014,1918.675 +13/10/2014,1891.65 +14/10/2014,1881.325 +15/10/2014,1857.9 +16/10/2014,1857.45 +17/10/2014,1878.7 +20/10/2014,1894.225 +21/10/2014,1925.65 +22/10/2014,1936.125 +23/10/2014,1943.7 +24/10/2014,1956.95 +27/10/2014,1960.15 +28/10/2014,1974.55 +29/10/2014,1981.5 +30/10/2014,1987.1 +31/10/2014,2009.65 +03/11/2014,2018.55 +04/11/2014,2011.225 +05/11/2014,2019.275 +06/11/2014,2025.5 +07/11/2014,2030.925 +10/11/2014,2034.8 +11/11/2014,2038.625 +12/11/2014,2037.075 +13/11/2014,2038.775 +14/11/2014,2039.225 +17/11/2014,2039.3 +18/11/2014,2047.725 +19/11/2014,2048.1 +20/11/2014,2048.25 +21/11/2014,2062.325 +24/11/2014,2067.45 +25/11/2014,2069.05 +26/11/2014,2070.025 +28/11/2014,2070.825 +01/12/2014,2058.65 +02/12/2014,2060.75 +03/12/2014,2071.175 +04/12/2014,2071.275 +05/12/2014,2074.625 +08/12/2014,2066.3 +09/12/2014,2052.8 +10/12/2014,2042.05 +11/12/2014,2036.65 +12/12/2014,2016.8 +15/12/2014,1998.9 +16/12/2014,1987.225 +17/12/2014,1994.325 +18/12/2014,2040.1 +19/12/2014,2067.625 +22/12/2014,2073.975 +23/12/2014,2082.55 +24/12/2014,2083.65 +26/12/2014,2087.525 +29/12/2014,2089.4 +30/12/2014,2084.2 +31/12/2014,2071.125 +02/01/2015,2058.875 +05/01/2015,2036.675 +06/01/2015,2011.85 +07/01/2015,2016.625 +08/01/2015,2046.85 +09/01/2015,2052.725 +12/01/2015,2036.575 +13/01/2015,2029.925 +14/01/2015,2009.125 +15/01/2015,2004.825 +16/01/2015,2005.05 +20/01/2015,2019.175 +21/01/2015,2025.65 +22/01/2015,2047.125 +23/01/2015,2057.075 +26/01/2015,2051.525 +27/01/2015,2036.3 +28/01/2015,2019.625 +29/01/2015,2009.375 +30/01/2015,2007.75 +02/02/2015,2005.025 +03/02/2015,2036.425 +04/02/2015,2045.45 +05/02/2015,2053.275 +06/02/2015,2060.05 +09/02/2015,2049.575 +10/02/2015,2059.375 +11/02/2015,2067.15 +12/02/2015,2079.25 +13/02/2015,2092.375 +17/02/2015,2096.975 +18/02/2015,2097.825 +19/02/2015,2097.375 +20/02/2015,2101 +23/02/2015,2108.15 +24/02/2015,2112.1 +25/02/2015,2114.675 +26/02/2015,2110.575 +27/02/2015,2107.975 +02/03/2015,2111.15 +03/03/2015,2109.425 +04/03/2015,2100.375 +05/03/2015,2099.725 +06/03/2015,2085.1 +09/03/2015,2076.825 +10/03/2015,2060.15 +11/03/2015,2043.675 +12/03/2015,2053.625 +13/03/2015,2055.95 +16/03/2015,2068.3 +17/03/2015,2075.15 +18/03/2015,2085.075 +19/03/2015,2093.075 +20/03/2015,2100.65 +23/03/2015,2107.925 +24/03/2015,2098.625 +25/03/2015,2078.175 +26/03/2015,2057.2 +27/03/2015,2058.15 +30/03/2015,2075.85 +31/03/2015,2075.775 +01/04/2015,2060.825 +02/04/2015,2064.125 +06/04/2015,2072.25 +07/04/2015,2080.75 +08/04/2015,2079.7 +09/04/2015,2085.025 +10/04/2015,2096.925 +13/04/2015,2098.6 +14/04/2015,2092.475 +15/04/2015,2103.525 +16/04/2015,2105.575 +17/04/2015,2089.7 +20/04/2015,2093.125 +21/04/2015,2101.025 +22/04/2015,2101.85 +23/04/2015,2110.95 +24/04/2015,2116.05 +27/04/2015,2115.275 +28/04/2015,2108.525 +29/04/2015,2107.6 +30/04/2015,2093.525 +01/05/2015,2097.875 +04/05/2015,2113.95 +05/05/2015,2101.45 +06/05/2015,2084.45 +07/05/2015,2083.975 +08/05/2015,2104.5 +11/05/2015,2110.8 +12/05/2015,2098.175 +13/05/2015,2101.075 +14/05/2015,2110.825 +15/05/2015,2121.375 +18/05/2015,2125.575 +19/05/2015,2128.675 +20/05/2015,2127.725 +21/05/2015,2128.4 +22/05/2015,2128.7 +26/05/2015,2113.5 +27/05/2015,2114.975 +28/05/2015,2119.575 +29/05/2015,2113.425 +01/06/2015,2110.5 +02/06/2015,2109.175 +03/06/2015,2114.05 +04/06/2015,2103.55 +05/06/2015,2093.65 +08/06/2015,2085.925 +09/06/2015,2079.25 +10/06/2015,2093.975 +11/06/2015,2109.075 +12/06/2015,2100.05 +15/06/2015,2084.875 +16/06/2015,2090.025 +17/06/2015,2098.375 +18/06/2015,2112.775 +19/06/2015,2115.525 +22/06/2015,2119.425 +23/06/2015,2123.825 +24/06/2015,2116.5 +25/06/2015,2107.525 +26/06/2015,2102.1 +29/06/2015,2077.85 +30/06/2015,2063.725 +01/07/2015,2073.55 +02/07/2015,2077.725 +06/07/2015,2069.925 +07/07/2015,2069.625 +08/07/2015,2061.7 +09/07/2015,2056.25 +10/07/2015,2065.825 +13/07/2015,2090.075 +14/07/2015,2104.7 +15/07/2015,2108.25 +16/07/2015,2117.475 +17/07/2015,2125.55 +20/07/2015,2127.9 +21/07/2015,2122.675 +22/07/2015,2115.225 +23/07/2015,2107.975 +24/07/2015,2091.25 +27/07/2015,2071.875 +28/07/2015,2082.175 +29/07/2015,2102 +30/07/2015,2105.225 +31/07/2015,2107.925 +03/08/2015,2098.875 +04/08/2015,2095.525 +05/08/2015,2100.775 +06/08/2015,2090.8 +07/08/2015,2077.675 +10/08/2015,2092.875 +11/08/2015,2091.5 +12/08/2015,2077.1 +13/08/2015,2085.2 +14/08/2015,2086.925 +17/08/2015,2093.575 +18/08/2015,2099.125 +19/08/2015,2085.5 +20/08/2015,2056.15 +21/08/2015,2002.5 +24/08/2015,1922.65 +25/08/2015,1895.2 +26/08/2015,1907.3 +27/08/2015,1965.725 +28/08/2015,1985.925 +31/08/2015,1977.9 +01/09/2015,1939.275 +02/09/2015,1932.7 +03/09/2015,1955.4 +04/09/2015,1932 +08/09/2015,1948.6 +09/09/2015,1960 +10/09/2015,1949.1 +11/09/2015,1953.175 +14/09/2015,1956.875 +15/09/2015,1967.675 +16/09/2015,1987.125 +17/09/2015,1998.275 +18/09/2015,1972.725 +21/09/2015,1965.8 +22/09/2015,1948.675 +23/09/2015,1941.025 +24/09/2015,1928.275 +25/09/2015,1935.4 +28/09/2015,1904.85 +29/09/2015,1884.35 +30/09/2015,1903.675 +01/10/2015,1917.85 +02/10/2015,1929.575 +05/10/2015,1971.2 +06/10/2015,1982.525 +07/10/2015,1988.45 +08/10/2015,2002.85 +09/10/2015,2014.075 +12/10/2015,2015.6 +13/10/2015,2010.7 +14/10/2015,1999.55 +15/10/2015,2010.275 +16/10/2015,2027.875 +19/10/2015,2030.55 +20/10/2015,2032.4 +21/10/2015,2026.9 +22/10/2015,2037.875 +23/10/2015,2067.825 +26/10/2015,2071.975 +27/10/2015,2065.975 +28/10/2015,2077.55 +29/10/2015,2088.2 +30/10/2015,2085.75 +02/11/2015,2092.975 +03/11/2015,2106.6 +04/11/2015,2106.125 +05/11/2015,2100.2 +06/11/2015,2095.85 +09/11/2015,2085 +10/11/2015,2078.125 +11/11/2015,2080.025 +12/11/2015,2059.075 +13/11/2015,2033.55 +16/11/2015,2036.975 +17/11/2015,2054.175 +18/11/2015,2068.225 +19/11/2015,2082.6 +20/11/2015,2087.975 +23/11/2015,2088.25 +24/11/2015,2084.475 +25/11/2015,2089.375 +27/11/2015,2089.075 +30/11/2015,2086.375 +01/12/2015,2092.95 +02/12/2015,2090.65 +03/12/2015,2064.4 +04/12/2015,2071.975 +07/12/2015,2081.175 +08/12/2015,2065.775 +09/12/2015,2056.4 +10/12/2015,2053.375 +11/12/2015,2028.95 +14/12/2015,2012.875 +15/12/2015,2037.075 +16/12/2015,2059.675 +17/12/2015,2058.45 +18/12/2015,2023.1 +21/12/2015,2015.075 +22/12/2015,2031.35 +23/12/2015,2053.35 +24/12/2015,2062.65 +28/12/2015,2054.075 +29/12/2015,2070.25 +30/12/2015,2070 +31/12/2015,2052.65 +04/01/2016,2019.7 +05/01/2016,2014.15 +06/01/2016,1998.175 +07/01/2016,1963.125 +08/01/2016,1936.725 +11/01/2016,1921.65 +12/01/2016,1932.05 +13/01/2016,1916.825 +14/01/2016,1906.725 +15/01/2016,1892.875 +19/01/2016,1884 +20/01/2016,1856 +21/01/2016,1867.325 +22/01/2016,1892.625 +25/01/2016,1891.425 +26/01/2016,1891.975 +27/01/2016,1893.8 +28/01/2016,1888.825 +29/01/2016,1917.1 +01/02/2016,1935.95 +02/02/2016,1917.725 +03/02/2016,1902.45 +04/02/2016,1913.75 +05/02/2016,1894.725 +08/02/2016,1857.075 +09/02/2016,1850.95 +10/02/2016,1860.225 +11/02/2016,1833.3 +12/02/2016,1849.1 +16/02/2016,1883.55 +17/02/2016,1913.775 +18/02/2016,1922.625 +19/02/2016,1913.875 +22/02/2016,1935.25 +23/02/2016,1931.375 +24/02/2016,1917.625 +25/02/2016,1940.2 +26/02/2016,1952.95 +29/02/2016,1942.35 +01/03/2016,1957.7 +02/03/2016,1979.6 +03/03/2016,1987.525 +04/03/2016,1997.475 +07/03/2016,1998.35 +08/03/2016,1987.625 +09/03/2016,1985.8 +10/03/2016,1988.725 +11/03/2016,2008.5 +14/03/2016,2018.875 +15/03/2016,2013.075 +16/03/2016,2020.85 +17/03/2016,2033.975 +18/03/2016,2046.1 +21/03/2016,2049.125 +22/03/2016,2048.9 +23/03/2016,2042.2 +24/03/2016,2031.725 +28/03/2016,2037.4 +29/03/2016,2043.75 +30/03/2016,2063.175 +31/03/2016,2062.225 +01/04/2016,2062.125 +04/04/2016,2068.975 +05/04/2016,2053.2 +06/04/2016,2055.675 +07/04/2016,2050.425 +08/04/2016,2048.85 +11/04/2016,2049.25 +12/04/2016,2052.55 +13/04/2016,2074.35 +14/04/2016,2082.9 +15/04/2016,2080.825 +18/04/2016,2085.375 +19/04/2016,2098.175 +20/04/2016,2102.825 +21/04/2016,2096.475 +22/04/2016,2089.65 +25/04/2016,2086.025 +26/04/2016,2091.05 +27/04/2016,2092.425 +28/04/2016,2084.4 +29/04/2016,2065.8 +02/05/2016,2074.525 +03/05/2016,2068.175 +04/05/2016,2054.3 +05/05/2016,2052.375 +06/05/2016,2050.525 +09/05/2016,2058.7 +10/05/2016,2073.625 +11/05/2016,2073.9 +12/05/2016,2064.6 +13/05/2016,2054.75 +16/05/2016,2057.9 +17/05/2016,2054.675 +18/05/2016,2046.775 +19/05/2016,2038.575 +20/05/2016,2048.6 +23/05/2016,2050.775 +24/05/2016,2065.3 +25/05/2016,2085.75 +26/05/2016,2090.725 +27/05/2016,2094.6 +31/05/2016,2097.325 +01/06/2016,2094.825 +02/06/2016,2099.225 +03/06/2016,2098.175 +06/06/2016,2106.1 +07/06/2016,2112.925 +08/06/2016,2116.275 +09/06/2016,2114.125 +10/06/2016,2101.325 +13/06/2016,2086.875 +14/06/2016,2074.35 +15/06/2016,2076.15 +16/06/2016,2068.6 +17/06/2016,2072.6 +20/06/2016,2083.775 +21/06/2016,2087.7 +22/06/2016,2089.825 +23/06/2016,2103.05 +24/06/2016,2069.4 +27/06/2016,2013.8 +28/06/2016,2021.4 +29/06/2016,2057.325 +30/06/2016,2085.25 +01/07/2016,2102.2 +05/07/2016,2089.925 +06/07/2016,2089.7 +07/07/2016,2099.2 +08/07/2016,2118.9 +11/07/2016,2135.95 +12/07/2016,2146.625 +13/07/2016,2152.2 +14/07/2016,2162.15 +15/07/2016,2162.925 +18/07/2016,2164.2 +19/07/2016,2162.8 +20/07/2016,2169.9 +21/07/2016,2168.125 +22/07/2016,2169.95 +25/07/2016,2169.45 +26/07/2016,2167.975 +27/07/2016,2167.625 +28/07/2016,2167.175 +29/07/2016,2170.75 +01/08/2016,2172.125 +02/08/2016,2161.175 +03/08/2016,2159.25 +04/08/2016,2163.75 +05/08/2016,2175.85 +08/08/2016,2181.975 +09/08/2016,2182.55 +10/08/2016,2178.425 +11/08/2016,2182.55 +12/08/2016,2183.375 +15/08/2016,2189.05 +16/08/2016,2182.175 +17/08/2016,2177.9 +18/08/2016,2184.1 +19/08/2016,2182.05 +22/08/2016,2181.35 +23/08/2016,2188.725 +24/08/2016,2179.6 +25/08/2016,2173.625 +26/08/2016,2173.1 +29/08/2016,2176.075 +30/08/2016,2177.05 +31/08/2016,2169.9 +01/09/2016,2168.225 +02/09/2016,2179 +06/09/2016,2182.45 +07/09/2016,2184.6 +08/09/2016,2181.625 +09/09/2016,2148.45 +12/09/2016,2140.575 +13/09/2016,2137.075 +14/09/2016,2128.725 +15/09/2016,2136.6 +16/09/2016,2140.85 +19/09/2016,2143.15 +20/09/2016,2143.925 +21/09/2016,2153.1 +22/09/2016,2174.75 +23/09/2016,2168.95 +26/09/2016,2152.025 +27/09/2016,2152.15 +28/09/2016,2164.35 +29/09/2016,2159.475 +30/09/2016,2164.15 +03/10/2016,2161.175 +04/10/2016,2155.85 +05/10/2016,2158.5 +06/10/2016,2158.05 +07/10/2016,2157.15 +10/10/2016,2163.525 +11/10/2016,2147.1 +12/10/2016,2138.775 +13/10/2016,2128.95 +14/10/2016,2138.725 +17/10/2016,2129.85 +18/10/2016,2139.45 +19/10/2016,2142.925 +20/10/2016,2141.1 +21/10/2016,2138.325 +24/10/2016,2150.375 +25/10/2016,2146.55 +26/10/2016,2138.425 +27/10/2016,2139.175 +28/10/2016,2129.675 +31/10/2016,2128.675 +01/11/2016,2117.4 +02/11/2016,2103.275 +03/11/2016,2093.825 +04/11/2016,2087.975 +07/11/2016,2116.175 +08/11/2016,2135 +09/11/2016,2147.575 +10/11/2016,2167.125 +11/11/2016,2161.375 +14/11/2016,2164.325 +15/11/2016,2173.975 +16/11/2016,2176.45 +17/11/2016,2182.625 +18/11/2016,2184.75 +21/11/2016,2192.425 +22/11/2016,2200.95 +23/11/2016,2200.625 +25/11/2016,2209.8 +28/11/2016,2205.85 +29/11/2016,2203.55 +30/11/2016,2204.175 +01/12/2016,2195.325 +02/12/2016,2192.325 +05/12/2016,2203.7 +06/12/2016,2208.625 +07/12/2016,2225.625 +08/12/2016,2244.15 +09/12/2016,2254.55 +12/12/2016,2258.05 +13/12/2016,2268.95 +14/12/2016,2261.55 +15/12/2016,2260.425 +16/12/2016,2261.8 +19/12/2016,2261.85 +20/12/2016,2269 +21/12/2016,2268.025 +22/12/2016,2260.8 +23/12/2016,2261.65 +27/12/2016,2268.775 +28/12/2016,2260.125 +29/12/2016,2249.475 +30/12/2016,2244.4 +03/01/2017,2254.6 +04/01/2017,2266.7 +05/01/2017,2267.275 +06/01/2017,2273.575 +09/01/2017,2271.725 +10/01/2017,2270.8 +11/01/2017,2270 +12/01/2017,2266.875 +13/01/2017,2274.375 +17/01/2017,2267.975 +18/01/2017,2269.075 +19/01/2017,2267.075 +20/01/2017,2270.825 +23/01/2017,2265.45 +24/01/2017,2274.825 +25/01/2017,2293.95 +26/01/2017,2297.6 +27/01/2017,2296.075 +30/01/2017,2280.225 +31/01/2017,2274.8 +01/02/2017,2281.675 +02/02/2017,2278.3 +03/02/2017,2293.025 +06/02/2017,2292.925 +07/02/2017,2294.65 +08/02/2017,2291.4 +09/02/2017,2303.075 +10/02/2017,2314.675 +13/02/2017,2325.725 +14/02/2017,2330.875 +15/02/2017,2342.725 +16/02/2017,2346.75 +17/02/2017,2346.25 +21/02/2017,2360.475 +22/02/2017,2361.825 +23/02/2017,2363.675 +24/02/2017,2360.8 +27/02/2017,2367.1 +28/02/2017,2364.125 +01/03/2017,2389.3 +02/03/2017,2387.925 +03/03/2017,2380.825 +06/03/2017,2374.325 +07/03/2017,2369.925 +08/03/2017,2366.725 +09/03/2017,2363 +10/03/2017,2371.25 +13/03/2017,2372 +14/03/2017,2365.2 +15/03/2017,2378.625 +16/03/2017,2383.6 +17/03/2017,2381.3 +20/03/2017,2375.25 +21/03/2017,2361.775 +22/03/2017,2344.9 +23/03/2017,2348.25 +24/03/2017,2346.575 +27/03/2017,2334.45 +28/03/2017,2349.95 +29/03/2017,2358.475 +30/03/2017,2364.6 +31/03/2017,2365.1 +03/04/2017,2357.925 +04/04/2017,2356.55 +05/04/2017,2362.1 +06/04/2017,2356.1 +07/04/2017,2356.65 +10/04/2017,2358.075 +11/04/2017,2350.025 +12/04/2017,2347.75 +13/04/2017,2337.025 +17/04/2017,2340.8 +18/04/2017,2341.875 +19/04/2017,2343.175 +20/04/2017,2350.2 +21/04/2017,2351.025 +24/04/2017,2372.675 +25/04/2017,2385.95 +26/04/2017,2390.35 +27/04/2017,2388.325 +28/04/2017,2388.5 +01/05/2017,2389.025 +02/05/2017,2390.25 +03/05/2017,2386.05 +04/05/2017,2387.75 +05/05/2017,2395.1 +08/05/2017,2398.65 +09/05/2017,2398.7 +10/05/2017,2397.225 +11/05/2017,2391.65 +12/05/2017,2390.725 +15/05/2017,2398.575 +16/05/2017,2401.8 +17/05/2017,2370.25 +18/05/2017,2362.2 +19/05/2017,2378.15 +22/05/2017,2390.9 +23/05/2017,2397.525 +24/05/2017,2402.35 +25/05/2017,2412.825 +26/05/2017,2414.8 +30/05/2017,2412.325 +31/05/2017,2411.75 +01/06/2017,2422.35 +02/06/2017,2434.575 +05/06/2017,2436.95 +06/06/2017,2431.375 +07/06/2017,2431.3 +08/06/2017,2433.825 +09/06/2017,2432.525 +12/06/2017,2426.425 +13/06/2017,2436.825 +14/06/2017,2438.45 +15/06/2017,2427.25 +16/06/2017,2430.125 +19/06/2017,2447.925 +20/06/2017,2443.75 +21/06/2017,2436.95 +22/06/2017,2436.7 +23/06/2017,2436.375 +26/06/2017,2442.45 +27/06/2017,2428.825 +28/06/2017,2435.1 +29/06/2017,2427.625 +30/06/2017,2426.75 +03/07/2017,2432.075 +05/07/2017,2430.075 +06/07/2017,2416.3 +07/07/2017,2419.775 +10/07/2017,2426.55 +11/07/2017,2423.725 +12/07/2017,2440.15 +13/07/2017,2445.95 +14/07/2017,2454.675 +17/07/2017,2459.65 +18/07/2017,2456.925 +19/07/2017,2468.8 +20/07/2017,2473.75 +21/07/2017,2469.375 +24/07/2017,2470.325 +25/07/2017,2477.775 +26/07/2017,2478.6 +27/07/2017,2475.525 +28/07/2017,2469.85 +31/07/2017,2473.175 +01/08/2017,2475.75 +02/08/2017,2476.225 +03/08/2017,2473.25 +04/08/2017,2476.45 +07/08/2017,2478.7 +08/08/2017,2478.6 +09/08/2017,2468.95 +10/08/2017,2451.7 +11/08/2017,2442.05 +14/08/2017,2461 +15/08/2017,2465.95 +16/08/2017,2468.875 +17/08/2017,2446.975 +18/08/2017,2428.55 +21/08/2017,2425.45 +22/08/2017,2443.7 +23/08/2017,2444.8 +24/08/2017,2443.375 +25/08/2017,2446 +28/08/2017,2444.9 +29/08/2017,2438.9 +30/08/2017,2451.95 +31/08/2017,2468.025 +01/09/2017,2476.3 +05/09/2017,2461.675 +06/09/2017,2464.525 +07/09/2017,2465.525 +08/09/2017,2462.525 +11/09/2017,2481.5 +12/09/2017,2493.9 +13/09/2017,2495.7 +14/09/2017,2494.975 +15/09/2017,2497.325 +18/09/2017,2503.65 +19/09/2017,2506 +20/09/2017,2505.125 +21/09/2017,2503.5 +22/09/2017,2499.875 +25/09/2017,2496.65 +26/09/2017,2499.1 +27/09/2017,2504.5 +28/09/2017,2506.8 +29/09/2017,2514.2 +02/10/2017,2524.975 +03/10/2017,2532.2 +04/10/2017,2535.875 +05/10/2017,2546.375 +06/10/2017,2547.475 +09/10/2017,2547.375 +10/10/2017,2550.175 +11/10/2017,2552.225 +12/10/2017,2551.85 +13/10/2017,2554.675 +16/10/2017,2556.325 +17/10/2017,2557.75 +18/10/2017,2562 +19/10/2017,2556.45 +20/10/2017,2571.45 +23/10/2017,2571.425 +24/10/2017,2568.9 +25/10/2017,2558.775 +26/10/2017,2561.85 +27/10/2017,2575.075 +30/10/2017,2574.7 +31/10/2017,2575.45 +01/11/2017,2581.475 +02/11/2017,2576.65 +03/11/2017,2583.725 +06/11/2017,2589.425 +07/11/2017,2591 +08/11/2017,2590.9 +09/11/2017,2580.35 +10/11/2017,2580.475 +13/11/2017,2580.875 +14/11/2017,2575.75 +15/11/2017,2566.05 +16/11/2017,2580.375 +17/11/2017,2580.825 +20/11/2017,2581.1 +21/11/2017,2594.65 +22/11/2017,2598.375 +24/11/2017,2601.85 +27/11/2017,2602.35 +28/11/2017,2616.5 +29/11/2017,2627.275 +30/11/2017,2643.275 +01/12/2017,2635.85 +04/12/2017,2650.2 +05/12/2017,2636.45 +06/12/2017,2628.675 +07/12/2017,2633.225 +08/12/2017,2648.375 +11/12/2017,2656 +12/12/2017,2663.825 +13/12/2017,2666.275 +14/12/2017,2659.5 +15/12/2017,2668.775 +18/12/2017,2689.25 +19/12/2017,2687.325 +20/12/2017,2683.625 +21/12/2017,2685.65 +22/12/2017,2682.725 +26/12/2017,2680.075 +27/12/2017,2682.3 +28/12/2017,2686 +29/12/2017,2682.125 +02/01/2018,2689.45 +03/01/2018,2705.775 +04/01/2018,2722.925 +05/01/2018,2736.45 +08/01/2018,2744.125 +09/01/2018,2752.375 +10/01/2018,2745.175 +11/01/2018,2760.25 +12/01/2018,2778.45 +16/01/2018,2787.875 +17/01/2018,2793.25 +18/01/2018,2799.7 +19/01/2018,2805.325 +22/01/2018,2820.825 +23/01/2018,2836.75 +24/01/2018,2840.175 +25/01/2018,2841.225 +26/01/2018,2859.875 +29/01/2018,2860.7 +30/01/2018,2827.8 +31/01/2018,2827.125 +01/02/2018,2821.775 +02/02/2018,2784.975 +05/02/2018,2697.9 +06/02/2018,2651 +07/02/2018,2695.4 +08/02/2018,2632.975 +09/02/2018,2598.2 +12/02/2018,2646.95 +13/02/2018,2653.775 +14/02/2018,2675.2 +15/02/2018,2716.5 +16/02/2018,2734.7 +20/02/2018,2720.925 +21/02/2018,2717.725 +22/02/2018,2710.875 +23/02/2018,2731.15 +26/02/2018,2767.85 +27/02/2018,2764.525 +28/02/2018,2735.65 +01/03/2018,2695.875 +02/03/2018,2673.4 +05/03/2018,2701.475 +06/03/2018,2725.425 +07/03/2018,2717.325 +08/03/2018,2733.725 +09/03/2018,2769.4 +12/03/2018,2787.45 +13/03/2018,2779.55 +14/03/2018,2761.275 +15/03/2018,2751.525 +16/03/2018,2753.6 +19/03/2018,2722.575 +20/03/2018,2716.575 +21/03/2018,2718.95 +22/03/2018,2668.1 +23/03/2018,2619.65 +26/03/2018,2635.275 +27/03/2018,2637.775 +28/03/2018,2610.525 +29/03/2018,2631.025 +02/04/2018,2601.85 +03/04/2018,2600.3 +04/04/2018,2613.05 +05/04/2018,2660.475 +06/04/2018,2623.375 +09/04/2018,2623.7 +10/04/2018,2649.125 +11/04/2018,2646.675 +12/04/2018,2661.575 +13/04/2018,2664.65 +16/04/2018,2674.9 +17/04/2018,2701.125 +18/04/2018,2709.95 +19/04/2018,2694.75 +20/04/2018,2679.3 +23/04/2018,2671.65 +24/04/2018,2654.075 +25/04/2018,2633.075 +26/04/2018,2660.575 +27/04/2018,2670.425 +30/04/2018,2663.525 +01/05/2018,2644.775 +02/05/2018,2645.625 +03/05/2018,2622.375 +04/05/2018,2642.75 +07/05/2018,2672.5 +08/05/2018,2668.425 +09/05/2018,2687.825 +10/05/2018,2714.675 +11/05/2018,2725.175 +14/05/2018,2732.775 +15/05/2018,2712.625 +16/05/2018,2718.775 +17/05/2018,2720.8 +18/05/2018,2714.75 +21/05/2018,2730.95 +22/05/2018,2731.7 +23/05/2018,2722.525 +24/05/2018,2724.525 +25/05/2018,2721.825 +29/05/2018,2695.625 +30/05/2018,2714.525 +31/05/2018,2712.375 +01/06/2018,2727.225 +04/06/2018,2744.575 +05/06/2018,2747.35 +06/06/2018,2761.6 +07/06/2018,2771.325 +08/06/2018,2771.95 +11/06/2018,2783.15 +12/06/2018,2785.25 +13/06/2018,2782.425 +14/06/2018,2782.825 +15/06/2018,2775.5 +18/06/2018,2767.925 +19/06/2018,2755.725 +20/06/2018,2768.95 +21/06/2018,2758.2 +22/06/2018,2758.15 +25/06/2018,2725.4 +26/06/2018,2723.425 +27/06/2018,2718.375 +28/06/2018,2707.825 +29/06/2018,2726.7 +02/07/2018,2714.45 +03/07/2018,2723.575 +05/07/2018,2728.65 +06/07/2018,2748.85 +09/07/2018,2776.475 +10/07/2018,2791.05 +11/07/2018,2777.625 +12/07/2018,2790.525 +13/07/2018,2798.6 +16/07/2018,2799.225 +17/07/2018,2800.575 +18/07/2018,2812.4 +19/07/2018,2806.45 +20/07/2018,2804.025 +23/07/2018,2802.475 +24/07/2018,2820.55 +25/07/2018,2832.375 +26/07/2018,2838.45 +27/07/2018,2828.15 +30/07/2018,2810.35 +31/07/2018,2814.65 +01/08/2018,2816.55 +02/08/2018,2813.475 +03/08/2018,2834.425 +06/08/2018,2845 +07/08/2018,2858.4 +08/08/2018,2857.5 +09/08/2018,2856.325 +10/08/2018,2835.225 +13/08/2018,2830.175 +14/08/2018,2834.4 +15/08/2018,2819.175 +16/08/2018,2838.5 +17/08/2018,2844.425 +20/08/2018,2855.35 +21/08/2018,2864.75 +22/08/2018,2861.6 +23/08/2018,2860.025 +24/08/2018,2868.875 +27/08/2018,2891.075 +28/08/2018,2899.05 +29/08/2018,2907.375 +30/08/2018,2904.425 +31/08/2018,2899.475 +04/09/2018,2894.75 +05/09/2018,2887.825 +06/09/2018,2881.525 +07/09/2018,2871.975 +10/09/2018,2880.325 +11/09/2018,2879.7 +12/09/2018,2887.775 +13/09/2018,2901.05 +14/09/2018,2903.875 +17/09/2018,2895.875 +18/09/2018,2899.15 +19/09/2018,2907.675 +20/09/2018,2926.25 +21/09/2018,2933.625 +24/09/2018,2919.4 +25/09/2018,2918.75 +26/09/2018,2914.375 +27/09/2018,2915.55 +28/09/2018,2913 +01/10/2018,2926.475 +02/10/2018,2924.5 +03/10/2018,2929.625 +04/10/2018,2906.15 +05/10/2018,2891.75 +08/10/2018,2878.35 +09/10/2018,2882.975 +10/10/2018,2829.625 +11/10/2018,2752.725 +12/10/2018,2760.7 +15/10/2018,2759.9 +16/10/2018,2789.35 +17/10/2018,2804.9 +18/10/2018,2783 +19/10/2018,2775.4 +22/10/2018,2764.475 +23/10/2018,2726.675 +24/10/2018,2697.125 +25/10/2018,2692.75 +26/10/2018,2661.8 +29/10/2018,2658.55 +30/10/2018,2661 +31/10/2018,2714.9 +01/11/2018,2727.125 +02/11/2018,2731.375 +05/11/2018,2731.725 +06/11/2018,2746.925 +07/11/2018,2794.325 +08/11/2018,2805.75 +09/11/2018,2783.35 +12/11/2018,2749.525 +13/11/2018,2730.475 +14/11/2018,2718.025 +15/11/2018,2707.475 +16/11/2018,2728.45 +19/11/2018,2708.925 +20/11/2018,2649.35 +21/11/2018,2657.025 +23/11/2018,2636.175 +26/11/2018,2661.925 +27/11/2018,2671.1 +28/11/2018,2715.9 +29/11/2018,2737.875 +30/11/2018,2747.925 +03/12/2018,2788.625 +04/12/2018,2741.4 +06/12/2018,2669.275 +07/12/2018,2664 +10/12/2018,2624.825 +11/12/2018,2649.2 +12/12/2018,2661.25 +13/12/2018,2654.175 +14/12/2018,2614.625 +17/12/2018,2567.075 +18/12/2018,2552.2 +19/12/2018,2532.1 +20/12/2018,2478.75 +21/12/2018,2448.75 +24/12/2018,2378.275 +26/12/2018,2411.3 +27/12/2018,2454.575 +28/12/2018,2494.425 +31/12/2018,2499.425 +02/01/2019,2493.5 +03/01/2019,2469.225 +04/01/2019,2504.65 +07/01/2019,2544.025 +08/01/2019,2567.475 +09/01/2019,2582.3 +10/01/2019,2582.475 +11/01/2019,2589.525 +14/01/2019,2580.65 +15/01/2019,2598.4 +16/01/2019,2617.35 +17/01/2019,2624.2 +18/01/2019,2661.275 +22/01/2019,2641.5 +23/01/2019,2637.075 +24/01/2019,2638.825 +25/01/2019,2662.975 +28/01/2019,2639.475 +29/01/2019,2641.725 +30/01/2019,2668.35 +31/01/2019,2694.3 +01/02/2019,2705.6 +04/02/2019,2713.8 +05/02/2019,2732.25 +06/02/2019,2732.25 +07/02/2019,2707.55 +08/02/2019,2697.55 +11/02/2019,2711.025 +12/02/2019,2734.525 +13/02/2019,2753.425 +14/02/2019,2744.575 +15/02/2019,2767.925 +19/02/2019,2775.925 +20/02/2019,2781.95 +21/02/2019,2775.325 +22/02/2019,2786.675 +25/02/2019,2802.225 +26/02/2019,2794.725 +27/02/2019,2787.7 +28/02/2019,2787.2 +01/03/2019,2799.325 +04/03/2019,2797.95 +05/03/2019,2790.875 +06/03/2019,2780.175 +07/03/2019,2755.425 +08/03/2019,2735.075 +11/03/2019,2765.625 +12/03/2019,2790.95 +13/03/2019,2807.925 +14/03/2019,2809.35 +15/03/2019,2818.7 +18/03/2019,2828.225 +19/03/2019,2837.275 +20/03/2019,2827.85 +21/03/2019,2838.075 +22/03/2019,2822.975 +25/03/2019,2797.3 +26/03/2019,2816.275 +27/03/2019,2809.6 +28/03/2019,2810.825 +29/03/2019,2829.475 +01/04/2019,2858.45 +02/04/2019,2866.775 +03/04/2019,2874.975 +04/04/2019,2875.45 +05/04/2019,2888.275 +08/04/2019,2890.25 +09/04/2019,2881.25 +10/04/2019,2884.6 +11/04/2019,2888.9 +12/04/2019,2904.3 +15/04/2019,2905 +16/04/2019,2909.05 +17/04/2019,2907.45 +18/04/2019,2902.525 +22/04/2019,2903.15 +23/04/2019,2922.125 +24/04/2019,2931.025 +25/04/2019,2925.275 +26/04/2019,2930.8 +29/04/2019,2943.1 +30/04/2019,2938.8 +01/05/2019,2938.375 +02/05/2019,2917.975 +03/05/2019,2937.95 +06/05/2019,2919.225 +07/05/2019,2893.175 +08/05/2019,2882.575 +09/05/2019,2860.725 +10/05/2019,2865.3 +13/05/2019,2823.425 +14/05/2019,2831.775 +15/05/2019,2836.3 +16/05/2019,2870.025 +17/05/2019,2864.45 +20/05/2019,2841.825 +21/05/2019,2860.325 +22/05/2019,2857.25 +23/05/2019,2825.275 +24/05/2019,2830.025 +28/05/2019,2818.625 +29/05/2019,2782.825 +30/05/2019,2787.875 +31/05/2019,2759.45 +03/06/2019,2746.95 +04/06/2019,2783.25 +05/06/2019,2818.125 +06/06/2019,2836.625 +07/06/2019,2866.025 +10/06/2019,2890.7 +11/06/2019,2894.525 +12/06/2019,2881.45 +13/06/2019,2888.75 +14/06/2019,2886.95 +17/06/2019,2891.025 +18/06/2019,2915.175 +19/06/2019,2922.55 +20/06/2019,2948.35 +21/06/2019,2953.575 +24/06/2019,2948.925 +25/06/2019,2931.425 +26/06/2019,2921.375 +27/06/2019,2923.125 +28/06/2019,2936.95 +01/07/2019,2966.45 +02/07/2019,2966.7 +03/07/2019,2986.925 +05/07/2019,2984.15 +08/07/2019,2976.65 +09/07/2019,2972.6 +10/07/2019,2992.5 +11/07/2019,2997.65 +12/07/2019,3008.25 +15/07/2019,3014.675 +16/07/2019,3008.075 +17/07/2019,2994.75 +18/07/2019,2986.35 +19/07/2019,2990.7 +22/07/2019,2983.575 +23/07/2019,2998.675 +24/07/2019,3008.7 +25/07/2019,3008.375 +26/07/2019,3019.925 +29/07/2019,3021.35 +30/07/2019,3009.75 +31/07/2019,2993.025 +01/08/2019,2973.175 +02/08/2019,2933.9 +05/08/2019,2865.75 +06/08/2019,2868.7 +07/08/2019,2865.15 +08/08/2019,2916.875 +09/08/2019,2921.3 +12/08/2019,2892.9 +13/08/2019,2906.85 +14/08/2019,2867.15 +15/08/2019,2844 +16/08/2019,2877.925 +19/08/2019,2920.425 +20/08/2019,2910.675 +21/08/2019,2923.25 +22/08/2019,2924.35 +23/08/2019,2880.05 +26/08/2019,2870.1 +27/08/2019,2880.425 +28/08/2019,2873.075 +29/08/2019,2917.8 +30/08/2019,2929.325 +03/09/2019,2905.375 +04/09/2019,2930.8 +05/09/2019,2970.775 +06/09/2019,2979.125 +09/09/2019,2981.4 +10/09/2019,2971.7 +11/09/2019,2989.625 +12/09/2019,3010.075 +13/09/2019,3009.95 +16/09/2019,2996.825 +17/09/2019,3000.325 +18/09/2019,2998.65 +19/09/2019,3010.6 +20/09/2019,3000.4 +23/09/2019,2989.175 +24/09/2019,2983.675 +25/09/2019,2973.975 +26/09/2019,2978.575 +27/09/2019,2970.025 +30/09/2019,2973.675 +01/10/2019,2963.775 +02/10/2019,2903.025 +03/10/2019,2890.75 +04/10/2019,2935.725 +07/10/2019,2944.625 +08/10/2019,2907.925 +09/10/2019,2916.8 +10/10/2019,2930.575 +11/10/2019,2972.45 +14/10/2019,2966.925 +15/10/2019,2986.55 +16/10/2019,2990.525 +17/10/2019,2999.7 +18/10/2019,2989.825 +21/10/2019,3001.45 +22/10/2019,3004.075 +23/10/2019,2998.625 +24/10/2019,3010.4 +25/10/2019,3013.8 +28/10/2019,3036.925 +29/10/2019,3038.75 +30/10/2019,3040.65 +31/10/2019,3038.65 +01/11/2019,3058.8 +04/11/2019,3079.35 +05/11/2019,3077.875 +06/11/2019,3074.025 +07/11/2019,3087.55 +08/11/2019,3085.25 +11/11/2019,3082.85 +12/11/2019,3092.1 +13/11/2019,3088.775 +14/11/2019,3092.225 +15/11/2019,3113.375 +18/11/2019,3119.05 +19/11/2019,3122.175 +20/11/2019,3108.4 +21/11/2019,3104.175 +22/11/2019,3108.475 +25/11/2019,3125.55 +26/11/2019,3137.25 +27/11/2019,3149.2 +29/11/2019,3144.45 +02/12/2019,3128.2 +03/12/2019,3086.475 +04/12/2019,3109.55 +05/12/2019,3114.95 +06/12/2019,3141.425 +09/12/2019,3140.575 +10/12/2019,3134.025 +11/12/2019,3138.65 +12/12/2019,3156.15 +13/12/2019,3168.675 +16/12/2019,3189.075 +17/12/2019,3194.275 +18/12/2019,3193.975 +19/12/2019,3198.875 +20/12/2019,3221.55 +23/12/2019,3225.05 +24/12/2019,3223.925 +26/12/2019,3233.6 +27/12/2019,3242.375 +30/12/2019,3229.725 +31/12/2019,3222.425 +02/01/2020,3249.025 +03/01/2020,3232.425 +06/01/2020,3231.325 +07/01/2020,3239.1 +08/01/2020,3248.875 +09/01/2020,3270 +10/01/2020,3272.75 +13/01/2020,3278.925 +14/01/2020,3284.975 +15/01/2020,3287.75 +16/01/2020,3309.925 +17/01/2020,3325.525 +21/01/2020,3322.05 +22/01/2020,3327.4 +23/01/2020,3317.525 +24/01/2020,3310.825 +27/01/2020,3246.025 +28/01/2020,3267.625 +29/01/2020,3282.075 +30/01/2020,3267.2 +31/01/2020,3251.2 +03/02/2020,3247.175 +04/02/2020,3291.425 +05/02/2020,3327.75 +06/02/2020,3343.275 +07/02/2020,3331.675 +10/02/2020,3335.125 +11/02/2020,3363 +12/02/2020,3375.275 +13/02/2020,3371.35 +14/02/2020,3376.3 +18/02/2020,3367.475 +19/02/2020,3384.725 +20/02/2020,3370.95 +21/02/2020,3346.875 +24/02/2020,3239.5 +25/02/2020,3183.225 +26/02/2020,3136.95 +27/02/2020,3028.95 +28/02/2020,2921.65 +02/03/2020,3025.175 +03/03/2020,3053.3 +04/03/2020,3085.325 +05/03/2020,3045.6 +06/03/2020,2953.5 +09/03/2020,2802.2 +10/03/2020,2828.075 +11/03/2020,2774.95 +12/03/2020,2562.825 +13/03/2020,2621.175 +16/03/2020,2459.65 +17/03/2020,2468.95 +18/03/2020,2392.175 +19/03/2020,2397.425 +20/03/2020,2371.35 +23/03/2020,2255.175 +24/03/2020,2396.45 +25/03/2020,2478.075 +26/03/2020,2567.275 +27/03/2020,2558.325 +30/03/2020,2590.7 +31/03/2020,2602.975 +01/04/2020,2484.725 +02/04/2020,2493.6 +03/04/2020,2500.45 +06/04/2020,2623.35 +07/04/2020,2703.175 +08/04/2020,2714.775 +09/04/2020,2786.95 +13/04/2020,2761.95 +14/04/2020,2827.025 +15/04/2020,2785.6 +16/04/2020,2792.425 +17/04/2020,2856.775 +20/04/2020,2839.55 +21/04/2020,2758.5 +22/04/2020,2794.55 +23/04/2020,2811.85 +24/04/2020,2820.95 +27/04/2020,2868.45 +28/04/2020,2888.825 +29/04/2020,2931.275 +30/04/2020,2916.675 +01/05/2020,2847.625 +04/05/2020,2824.925 +05/05/2020,2874.775 +06/05/2020,2867.575 +07/05/2020,2884.475 +08/05/2020,2918.425 +11/05/2020,2923.35 +12/05/2020,2906.25 +13/05/2020,2838.3 +14/05/2020,2816.6 +15/05/2020,2843.85 +18/05/2020,2937.45 +19/05/2020,2939.5 +20/05/2020,2964.775 +21/05/2020,2958.875 +22/05/2020,2948.475 +26/05/2020,3001.45 +27/05/2020,3014.45 +28/05/2020,3042.1 +29/05/2020,3029.325 +01/06/2020,3047.05 +02/06/2020,3069.575 +03/06/2020,3112.9 +04/06/2020,3110.8 +05/06/2020,3183.3 +08/06/2020,3215.35 +09/06/2020,3209.075 +10/06/2020,3202.075 +11/06/2020,3062.15 +12/06/2020,3046.3 +15/06/2020,3026.475 +16/06/2020,3121.3 +17/06/2020,3124.7 +18/06/2020,3107.6 +19/06/2020,3119.15 +22/06/2020,3103.15 +23/06/2020,3138 +24/06/2020,3077.95 +25/06/2020,3060.15 +26/06/2020,3040.15 +29/06/2020,3031.35 +30/06/2020,3077.45 +01/07/2020,3112.85 +02/07/2020,3140.975 +06/07/2020,3168.225 +07/07/2020,3159.7 +08/07/2020,3157.825 +09/07/2020,3155.95 +10/07/2020,3165.125 +13/07/2020,3186.25 +14/07/2020,3166.8 +15/07/2020,3222.925 +16/07/2020,3210.75 +17/07/2020,3222.025 +20/07/2020,3237.475 +21/07/2020,3262.725 +22/07/2020,3265.825 +23/07/2020,3252.5 +24/07/2020,3215.4 +27/07/2020,3228.7 +28/07/2020,3228.15 +29/07/2020,3244.375 +30/07/2020,3233.25 +31/07/2020,3258.5 +03/08/2020,3292.525 +04/08/2020,3297.4 +05/08/2020,3323.35 +06/08/2020,3335.375 +07/08/2020,3343.15 +10/08/2020,3353.8 +11/08/2020,3352.85 +12/08/2020,3369.8 +13/08/2020,3374.2 +14/08/2020,3370.4 +17/08/2020,3382.425 +18/08/2020,3385.525 +19/08/2020,3384.125 +20/08/2020,3372.875 +21/08/2020,3390.625 +24/08/2020,3423.65 +25/08/2020,3437.375 +26/08/2020,3463.5 +27/08/2020,3484.85 +28/08/2020,3499.05 +31/08/2020,3504.5 +01/09/2020,3514.175 +02/09/2020,3561.975 +03/09/2020,3503 +04/09/2020,3427.35 +08/09/2020,3353.25 +09/09/2020,3390.1 +10/09/2020,3376.65 +11/09/2020,3343.275 +14/09/2020,3378.4 +15/09/2020,3404.4 +16/09/2020,3402.5 +17/09/2020,3351.975 +18/09/2020,3332.9 +21/09/2020,3270.35 +22/09/2020,3300.65 +23/09/2020,3278.225 +24/09/2020,3240.2 +25/09/2020,3267.625 +28/09/2020,3344.775 +29/09/2020,3342.95 +30/09/2020,3359.575 +01/10/2020,3381.325 +02/10/2020,3345.025 +05/10/2020,3388.2 +06/10/2020,3388.925 +07/10/2020,3403.725 +08/10/2020,3439.15 +09/10/2020,3469.3 +12/10/2020,3520.9 +13/10/2020,3520.2 +14/10/2020,3503.175 +15/10/2020,3466.75 +16/10/2020,3493.375 +19/10/2020,3460.725 +20/10/2020,3448.775 +21/10/2020,3443.375 +22/10/2020,3441.95 +23/10/2020,3459.3 +26/10/2020,3412.175 +27/10/2020,3398.025 +28/10/2020,3306.225 +29/10/2020,3297.05 +30/10/2020,3275.6 +02/11/2020,3304.05 +03/11/2020,3357.775 +04/11/2020,3435.325 +05/11/2020,3502.725 +06/11/2020,3505.9 +09/11/2020,3581.75 +10/11/2020,3539.475 +11/11/2020,3568.525 +12/11/2020,3546.825 +13/11/2020,3571.025 +16/11/2020,3613.95 +17/11/2020,3607.9 +18/11/2020,3591.575 +19/11/2020,3567.575 +20/11/2020,3568.7 +23/11/2020,3571.75 +24/11/2020,3616.675 +25/11/2020,3629.625 +27/11/2020,3637.625 +30/11/2020,3621.1 +01/12/2020,3658.15 +02/12/2020,3659.65 +03/12/2020,3668.725 +04/12/2020,3685.025 +07/12/2020,3690.75 +08/12/2020,3693.125 +09/12/2020,3687.925 +10/12/2020,3662.725 +11/12/2020,3654.725 +14/12/2020,3666.55 +15/12/2020,3678.975 +16/12/2020,3699.325 +17/12/2020,3718.05 +18/12/2020,3711.075 +21/12/2020,3679.65 +22/12/2020,3689.975 +23/12/2020,3695.975 +24/12/2020,3697.55 +28/12/2020,3730.475 +29/12/2020,3739.1 +30/12/2020,3735.75 +31/12/2020,3744.125 +04/01/2021,3724.5 +05/01/2021,3714.45 +06/01/2021,3737.15 +07/01/2021,3786.2 +08/01/2021,3812.525 +11/01/2021,3802.4 +12/01/2021,3797.525 +13/01/2021,3806.125 +14/01/2021,3806.75 +15/01/2021,3773.8 +19/01/2021,3791.425 +20/01/2021,3836 +21/01/2021,3854.275 +22/01/2021,3842.1 +25/01/2021,3840.875 +26/01/2021,3857.825 +27/01/2021,3789.225 +28/01/2021,3782.375 +29/01/2021,3741.125 +01/02/2021,3753.75 +02/02/2021,3813.25 +03/02/2021,3833.675 +04/02/2021,3854.375 +05/02/2021,3883.65 +08/02/2021,3904.15 +09/02/2021,3910.65 +10/02/2021,3911.775 +11/02/2021,3912.3 +12/02/2021,3922.375 +16/02/2021,3936.6 +17/02/2021,3920.95 +18/02/2021,3909.225 +19/02/2021,3915.35 +22/02/2021,3884.925 +23/02/2021,3860.025 +24/02/2021,3896.85 +25/02/2021,3871.025 +26/02/2021,3825.375 +01/03/2021,3875.325 +02/03/2021,3887.225 +03/03/2021,3844.275 +04/03/2021,3788.5 +05/03/2021,3804.35 +08/03/2021,3841.5 +09/03/2021,3870.75 +10/03/2021,3898.45 +11/03/2021,3932.65 +12/03/2021,3932 +15/03/2021,3951.375 +16/03/2021,3967.675 +17/03/2021,3960.825 +18/03/2021,3937.375 +19/03/2021,3910.775 +22/03/2021,3931.65 +23/03/2021,3924.7 +24/03/2021,3910.05 +25/03/2021,3890.45 +26/03/2021,3946.725 +29/03/2021,3966.35 +30/03/2021,3958.55 +31/03/2021,3975.375 +01/04/2021,4006.525 +05/04/2021,4057.525 +06/04/2021,4075.95 +07/04/2021,4076.4 +08/04/2021,4091.95 +09/04/2021,4112.475 +12/04/2021,4124.825 +13/04/2021,4136.025 +14/04/2021,4134.725 +15/04/2021,4155.875 +16/04/2021,4180.425 +19/04/2021,4168.6 +20/04/2021,4142.925 +21/04/2021,4150.8 +22/04/2021,4152.2 +23/04/2021,4163 +26/04/2021,4187.3 +27/04/2021,4186.125 +28/04/2021,4187.9 +29/04/2021,4203.3 +30/04/2021,4188.075 +03/05/2021,4195.525 +04/05/2021,4162.825 +05/05/2021,4173.325 +06/05/2021,4180.175 +07/05/2021,4220.625 +10/05/2021,4210.3 +11/05/2021,4143.975 +12/05/2021,4096.3 +13/05/2021,4098.525 +14/05/2021,4154.05 +17/05/2021,4161.95 +18/05/2021,4147.2 +19/05/2021,4098.1 +20/05/2021,4143.975 +21/05/2021,4166.225 +24/05/2021,4186.75 +25/05/2021,4197.475 +26/05/2021,4193.575 +27/05/2021,4203.5 +28/05/2021,4209.225 +01/06/2021,4212.55 +02/06/2021,4207.65 +03/06/2021,4189.15 +04/06/2021,4218.875 +07/06/2021,4225.95 +08/06/2021,4226.55 +09/06/2021,4227.1 +10/06/2021,4234.45 +11/06/2021,4242.725 +14/06/2021,4248.275 +15/06/2021,4249.375 +16/06/2021,4231.725 +17/06/2021,4217.675 +18/06/2021,4185.1 +21/06/2021,4199.45 +22/06/2021,4236.025 +23/06/2021,4247.275 +24/06/2021,4262.95 +25/06/2021,4278.1 +28/06/2021,4285.575 +29/06/2021,4293.125 +30/06/2021,4294.625 +01/07/2021,4310.5 +02/07/2021,4340.225 +06/07/2021,4342.725 +07/07/2021,4350.2 +08/07/2021,4315.55 +09/07/2021,4350 +12/07/2021,4376.925 +13/07/2021,4377.4 +14/07/2021,4377.625 +15/07/2021,4359.675 +16/07/2021,4348.05 +19/07/2021,4271.1 +20/07/2021,4296.775 +21/07/2021,4345.15 +22/07/2021,4362.2 +23/07/2021,4397.35 +26/07/2021,4415 +27/07/2021,4401.7 +28/07/2021,4401.5 +29/07/2021,4414.075 +30/07/2021,4398.05 +02/08/2021,4400.275 +03/08/2021,4403.15 +04/08/2021,4408.75 +05/08/2021,4419.175 +06/08/2021,4433.875 +09/08/2021,4433.575 +10/08/2021,4436.95 +11/08/2021,4443.925 +12/08/2021,4451.175 +13/08/2021,4465.5 +16/08/2021,4464.825 +17/08/2021,4447.525 +18/08/2021,4423.275 +19/08/2021,4393.625 +20/08/2021,4425.875 +23/08/2021,4467.5 +24/08/2021,4486.425 +25/08/2021,4493.5 +26/08/2021,4482.175 +27/08/2021,4492.725 +30/08/2021,4523.45 +31/08/2021,4524.925 +01/09/2021,4528 +02/09/2021,4535.5 +03/09/2021,4532.625 +07/09/2021,4525.95 +08/09/2021,4511.975 +09/09/2021,4507.075 +10/09/2021,4485.925 +13/09/2021,4470.55 +14/09/2021,4460.9 +15/09/2021,4463.375 +16/09/2021,4470.15 +17/09/2021,4450.5 +20/09/2021,4367.35 +21/09/2021,4367.875 +22/09/2021,4386.8 +23/09/2021,4432 +24/09/2021,4446.725 +27/09/2021,4444.675 +28/09/2021,4384.475 +29/09/2021,4365.65 +30/09/2021,4341.75 +01/10/2021,4334.475 +04/10/2021,4320.925 +05/10/2021,4333.675 +06/10/2021,4334.825 +07/10/2021,4399.3 +08/10/2021,4399 +11/10/2021,4380.775 +12/10/2021,4358.975 +13/10/2021,4356.15 +14/10/2021,4412.9 +15/10/2021,4460.65 +18/10/2021,4471.625 +19/10/2021,4508.425 +20/10/2021,4531.475 +21/10/2021,4540.075 +22/10/2021,4543.675 +25/10/2021,4557.55 +26/10/2021,4580.3 +27/10/2021,4567.05 +28/10/2021,4579.9 +29/10/2021,4588.5 +01/11/2021,4609.925 +02/11/2021,4623.075 +03/11/2021,4643.975 +04/11/2021,4672.15 +05/11/2021,4699.15 +08/11/2021,4703.125 +09/11/2021,4692.95 +10/11/2021,4658.2 +11/11/2021,4655.4 +12/11/2021,4669.35 +15/11/2021,4685.6 +16/11/2021,4693.65 +17/11/2021,4694.025 +18/11/2021,4696.7 +19/11/2021,4704.6 +22/11/2021,4705.225 +23/11/2021,4680.325 +24/11/2021,4685.025 +26/11/2021,4627.3 +29/11/2021,4645.575 +30/11/2021,4603.3 +01/12/2021,4569.75 +02/12/2021,4545.5 +03/12/2021,4557.75 +06/12/2021,4573.3 +07/12/2021,4661.2 +08/12/2021,4692.925 +09/12/2021,4679.925 +10/12/2021,4695.85 +13/12/2021,4689.3 +14/12/2021,4636.025 +15/12/2021,4667.55 +16/12/2021,4692.925 +17/12/2021,4635 +20/12/2021,4568.725 +21/12/2021,4619.625 +22/12/2021,4672.55 +23/12/2021,4718.625 +27/12/2021,4762.675 +28/12/2021,4792.225 +29/12/2021,4790.975 +30/12/2021,4789.275 +31/12/2021,4773.5 \ No newline at end of file diff --git a/QuantumPhaseEstimation.ipynb b/QuantumPhaseEstimation.ipynb new file mode 100644 index 0000000..c4e1b74 --- /dev/null +++ b/QuantumPhaseEstimation.ipynb @@ -0,0 +1,199 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Analyzing matrix:\n", + "[[0.99500417-0.09983342j 0. +0.j ]\n", + " [0. +0.j 0.99500417-0.09983342j]]\n", + "\n", + "Results:\n", + "Estimated primary phase: 0.0000\n", + "Number of zero phases detected: 1\n", + "\n", + "Final result: 1 zero eigenvalues detected\n" + ] + } + ], + "source": [ + "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile\n", + "from qiskit_aer import AerSimulator\n", + "from qiskit.quantum_info import Operator\n", + "from qiskit.visualization import plot_histogram\n", + "import numpy as np\n", + "import math\n", + "\n", + "pi=np.pi\n", + "\n", + "def qft_rot(circuit, n):\n", + " if n == 0:\n", + " return circuit\n", + " \n", + " n = n-1\n", + " circuit.h(n)\n", + " for i in range(n):\n", + " circuit.cp(pi/(2**(n-i)), i, n)\n", + " \n", + " qft_rot(circuit, n)\n", + " \n", + "def iqft_rot(circuit, n):\n", + " for i in range(n):\n", + " if i > 0:\n", + " for j in range(i, 0, -1):\n", + " circuit.cp(-pi/(2**j), i, i-j)\n", + " circuit.h(i) \n", + " return circuit\n", + "\n", + "def phase_estimation(oracle, eigenstate, number_qubits):\n", + " n = number_qubits\n", + " qr = QuantumRegister(n+1, 'q')\n", + " c = ClassicalRegister(n, 'c')\n", + " qc = QuantumCircuit(qr, c)\n", + " \n", + " if eigenstate == 1:\n", + " qc.x(n)\n", + " \n", + " for i in range(n//2):\n", + " qc.swap(i, n-i-1)\n", + " \n", + " for i in range(3):\n", + " qc.h(i) \n", + " \n", + " cGate = oracle.control(1)\n", + " qc.barrier()\n", + " \n", + " for i in range(n):\n", + " for j in range(2**i):\n", + " qc.append(cGate, [i, n])\n", + " \n", + " qc.barrier()\n", + " iqft_rot(qc, n+1)\n", + " qc.barrier()\n", + " \n", + " for i in range(n):\n", + " qc.measure(i, i)\n", + " \n", + " aersim = AerSimulator(shots=1000)\n", + " circuit_transpile = transpile(qc, aersim)\n", + " result = aersim.run(circuit_transpile).result()\n", + " counts = result.get_counts()\n", + " \n", + " # Get the most common bitstring and convert to phase\n", + " most_common_bitstring = max(counts, key=counts.get)\n", + " N = len(most_common_bitstring)\n", + " phase = int(most_common_bitstring, 2) / 2**N\n", + " \n", + " hist = plot_histogram(counts, title=f\"Phase Estimation for |{1}>\")\n", + " \n", + " return counts, phase, qc\n", + "\n", + "def create_gate_from_matrix(matrix):\n", + " \"\"\"\n", + " Create a quantum circuit from a nxn unitary matrix\n", + " \"\"\"\n", + " n = matrix.shape[0]\n", + " n_qubits = int(math.log2(n))\n", + " qc = QuantumCircuit(1) # We only need 1 qubit for 2x2 matrix\n", + " \n", + " op = Operator(matrix)\n", + " qc.unitary(op, [0], label='L')\n", + " \n", + " return qc\n", + "\n", + "def analyze_phases(counts, n_qubits, zero_threshold=1e-3):\n", + " \"\"\"\n", + " Analyze phases from measurement results and count zero phases\n", + " \"\"\"\n", + " total_shots = sum(counts.values())\n", + " phases = {}\n", + " zero_phase_count = 0\n", + " \n", + " for bitstring, count in counts.items():\n", + " phase = int(bitstring, 2) / (2**n_qubits)\n", + " probability = count / total_shots\n", + " phases[phase] = probability\n", + " \n", + " if phase < zero_threshold:\n", + " zero_phase_count += 1\n", + " \n", + " return phases, zero_phase_count\n", + "\n", + "def analyze_matrix(matrix, n_qubits=4, zero_threshold=1e-3):\n", + " \"\"\"\n", + " Analyze a matrix using QPE to detect zero eigenvalues\n", + " \"\"\"\n", + " \n", + " # Create gate from matrix\n", + " gate = create_gate_from_matrix(matrix)\n", + " \n", + " # Run phase estimation\n", + " counts, estimated_phase, _ = phase_estimation(gate, 1, n_qubits)\n", + " \n", + " # Analyze phases and count zeros\n", + " phases, zero_count = analyze_phases(counts, n_qubits, zero_threshold)\n", + " \n", + " print(f\"\\nResults:\")\n", + " print(f\"Estimated primary phase: {estimated_phase:.4f}\")\n", + " print(f\"Number of zero phases detected: {zero_count}\")\n", + " \n", + " return zero_count\n", + "\n", + "L = np.array([[0.99500417-0.09983342j, 0],\n", + " [0, 0.99500417-0.09983342j]])\n", + "\n", + "print(\"Analyzing matrix:\")\n", + "print(L)\n", + "n_zeros = analyze_matrix(L)\n", + "print(f\"\\nFinal result: {n_zeros} zero eigenvalues detected\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.6" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/betti_analysis.svg b/betti_analysis.svg new file mode 100644 index 0000000..d93241d --- /dev/null +++ b/betti_analysis.svg @@ -0,0 +1,26677 @@ + + + + + + + + 2025-02-01T19:07:37.177854 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/betti_analysis_norm.svg b/betti_analysis_norm.svg new file mode 100644 index 0000000..4812a6b --- /dev/null +++ b/betti_analysis_norm.svg @@ -0,0 +1,5416 @@ + + + + + + + + 2025-02-01T21:18:06.080276 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/betti_analysis_norm_1.svg b/betti_analysis_norm_1.svg new file mode 100644 index 0000000..88c19df --- /dev/null +++ b/betti_analysis_norm_1.svg @@ -0,0 +1,6222 @@ + + + + + + + + 2025-02-01T21:24:55.748536 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/betti_analysis_norm_L1.svg b/betti_analysis_norm_L1.svg new file mode 100644 index 0000000..9d2f06d --- /dev/null +++ b/betti_analysis_norm_L1.svg @@ -0,0 +1,34933 @@ + + + + + + + + 2025-02-01T22:00:20.666392 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/betti_analysis_norm_L1_housing.svg b/betti_analysis_norm_L1_housing.svg new file mode 100644 index 0000000..4b99f57 --- /dev/null +++ b/betti_analysis_norm_L1_housing.svg @@ -0,0 +1,4459 @@ + + + + + + + + 2025-02-02T09:25:40.782439 + image/svg+xml + + + Matplotlib v3.4.2, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/moodys_challenge final.ipynb b/moodys_challenge final.ipynb new file mode 100644 index 0000000..b0f30b1 --- /dev/null +++ b/moodys_challenge final.ipynb @@ -0,0 +1,2714 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "de7fe4be-dd2d-4d8c-9358-5ab6a636496e", + "metadata": {}, + "source": [ + "# Quantum Machine Learning for detecting financial crashes" + ] + }, + { + "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.** How to use classical topological data analysis, TDA, for financial bubble early warning?
\n", + "**2.** How to implement its quantum counterpart?
\n", + "**3.** Conduct a resource analysis on the quantum algorithm. Which step is most costly?
\n", + "**4.** Get used to Quantum Phase Estimation, QPE.
\n", + "**5.** How is the influence of the classical noise (the random fluctuations in financial markets)?
\n", + "**6.** How is the influence of quantum noise?
" + ] + }, + { + "cell_type": "markdown", + "id": "85d339f8-0a2d-4c84-88d2-ae2f5d7e7597", + "metadata": {}, + "source": [ + "## The challenge" + ] + }, + { + "cell_type": "markdown", + "id": "ddf18fd5", + "metadata": {}, + "source": [ + "### Main idea\n", + "\n", + "Topological Data Analysis (TDA) is a robust and innovative technique that has demonstrated impressive results in detecting financial crashes—critical transitions between financial regimes—and providing early warning signals. By analyzing changes in Betti numbers, TDA can reveal shifts in underlying structures that precede these transitions. In this notebook, we employ a quantum TDA algorithm to calculate Betti numbers, enabling effective early detection of financial crashes.\n", + "\n", + "### What is topological data analysis\n", + "\n", + "Topology studies the properties of geometric objects that are preserved under continuous deformations, such as stretching, twisting, crumpling, and bending. Homology serves as a tool to study and quantify the topological properties of spaces. The homology of an object is often summarized using $k$-th Betti numbers, which count the number of $k$-dimensional holes within the object. For example, the zeroth Betti number, $\\beta_0$, counts the number of connected components; the first Betti number, $\\beta_1$, counts the number of loops; and the second Betti number, $\\beta_2$, counts the number of enclosed volumes, and so on.\n", + "\n", + "In finance, input data is typically represented as time series, which are subsequently transformed into a series of discrete points. To model the underlying structure with them, we construct a simplicial complex (specifically, a Vietoris–Rips complex), a collection of simple shapes that connect the points together. Those simple shapes are called simplex, and they are generalization of the notion of a triangle or tetrahedron to arbitrary dimensions. A $k$-simplex is a collection of $k + 1$ vertices with $k(k + 1)/2$ edges in $k$ dimensions. A resolution threshold, $\\epsilon$, is chosen so that any two points within $\\epsilon$ distance of each other are connected by a line segment in the simplicial complex. As $\\epsilon$ increases, more connections are added, and lower-order components may merge into higher-order components. This results in a decrease in the lower-order Betti numbers and an increase in the higher-order Betti numbers. The study of how topological properties change across a sequence of resolution thresholds is called persistent homology.\n", + "\n", + "\"Description\n", + "\n", + "For example, consider the figure above, which consists of five points. When $\\epsilon$ is small, no lines connect the points. Consequently, $\\beta_0 = 5$, as there are five discrete points, each representing an independent connected component, and no higher-dimensional features are present. As $\\epsilon$ increases, the Betti numbers for the configuration on the right become:\n", + "\n", + "* $\\beta_0=2$: There are two connected components (a line segment and a triangle).\n", + "* $\\beta_1=1$: There is one 1-dimensional hole (the triangle encloses a region).\n", + "* $\\beta_k=0$ for $k\\ge2$: No higher-dimensional features exist.\n", + "\n", + "This example also illustrates how Betti numbers change with the resolution threshold. The sequence of Betti numbers as the resolution threshold varies forms a curve known as the Betti curve. This curve can be utilized as input for kernel construction in machine learning applications.\n", + "\n", + "### What is quantum TDA?\n", + "\n", + "TDA can be used for extracting complex and valuable shape-related summaries of high-dimensional data. However, as the size of the dataset grows, the number of simplices considered increases significantly, leading to an exponential rise in the computational complexity of TDA algorithms ([ref](https://quantum-journal.org/papers/q-2022-11-10-855/)). \n", + "\n", + "Quantum computers have the potential to significantly accelerate TDA algorithms. Lloyd et al. introduced a fully quantum TDA algorithm leveraging quantum random access memory (qRAM), Grover's search algorithm, and quantum phase estimation (QPE) ([ref](https://www.nature.com/articles/ncomms10138)). In this approach, classical data is first loaded and encoded into the quantum amplitudes of a quantum state via qRAM. Grover's algorithm is then employed to construct the simplex state, with a membership function used to determine whether a given simplex belongs to the complex. Finally, the combinatorial Laplacian (also referred to as the \"Dirac operator\") is constructed, and the Betti numbers—key topological invariants—are extracted using QPE. \n", + "\n", + "However, this quantum TDA algorithm is really costly for NISQ computers. Even more, the qRAM requires long-lasting quantum coherence and low computational error to store and process the loaded data. Several exciting alternatives approaches have been proposed since then. It must be noted that quantum TDA is one of the first quantum machine learning algorithms with short depth and potential significant speedup under certain assumptions.\n", + "\n", + "Here is a list of different versions of quantum TDA. Note that they may be beyond the scope of this challenge, and mainly for your interest:\n", + "\n", + "* [QTDA via the estimation of the density of states (December 2023, University of Exeter)](https://arxiv.org/abs/2312.07115)\n", + "* [NISQ-TDA (Sep 2022, IBM Research + University of the Witwatersrand)](https://arxiv.org/pdf/2209.09371)\n", + "* [Quantum persistent homology (Nov 2022, University of Tennessee)](https://arxiv.org/abs/2211.04465)\n", + "* [Hybrid qTDA (Oct 2022, Deloitte)](https://arxiv.org/abs/2209.10596)\n", + "* [Quantum-Enhanced TDA (Feb 2023, Tata Consultancy Services)](https://arxiv.org/pdf/2302.09553)\n", + "\n", + "### Does TDA have applications in finance?\n", + "\n", + "Betti numbers offer valuable insights into the structure and shape of complex data. While their use in finance is still in its early stages, they show promise in various applications, such as credit risk prediction ([ref](https://ora.ox.ac.uk/objects/uuid:9f4bed48-1763-486f-acbe-393670fab6bb/files/skw52j939s)), fraud detection, financial bubble detection ([ref](https://arxiv.org/abs/2304.06877)), capturing financial instability ([ref](https://arxiv.org/pdf/2110.00098)), etc. It can also be used as an unsupervised learning algorithm for anomaly detection.\n", + "\n", + "Several studies suggest that Betti numbers serve as effective indicators of market crashes. The zeroth betti number $\\beta_0$ is small at the beginning of a market crash and increases as the market crash progresses. It can be interpreted as that there is a giant connected component in the market just before the crash, and as the market crashed, this broke up into many smaller components ([ref](https://www.mdpi.com/1099-4300/23/9/1211), [ref](https://www.frontiersin.org/journals/physics/articles/10.3389/fphy.2021.572216/full)). \n", + "\n", + "This concept serves as the foundation for the idea behind this challenge." + ] + }, + { + "cell_type": "markdown", + "id": "7d128bf0", + "metadata": {}, + "source": [ + "## Problem Statement - Detecting financial bubbles by using quantum topological data analysis (qTDA)" + ] + }, + { + "cell_type": "markdown", + "id": "cfe38b05-e39a-4d01-a1d6-b6fafcec3db3", + "metadata": {}, + "source": [ + "The goal of this challenge is to build a quantum TDA pipeline for detecting financial market crashes. The process is outlined in the following key steps, with detailed instructions provided below. Follow the **Instructions** and **Action** parts carefully and implement the necessary code after **Answer** to complete the pipeline.\n", + "\n", + "These references deal with the problem at hand and can be helpful to consult:\n", + "* [Quantum-Enhanced Topological Data Analysis: A Peep from an Implementation Perspective](https://arxiv.org/pdf/2302.09553)\n", + "* [Towards Quantum Advantage via Topological Data Analysis](https://quantum-journal.org/papers/q-2022-11-10-855/)\n", + "\n", + "
\n", + " \n", + "**STEPS**\n", + " \n", + "* Input: a time series of stock price; Output: a time-evolution of topological properties.\n", + "\n", + "* Preparing point cloud\n", + " * Apply Taken's embedding.\n", + " * Apply a sliding window for obatining a time-varying point-cloud.\n", + "* Building Laplacian\n", + " * Construct the Vietoris-Rips (VR) complex from the point cloud using [`GUDHI`](https://gudhi.inria.fr/).\n", + " * Build the boudnary operator of this complex.\n", + " * Build the Laplacian matrix based on the boundary operators, then pad it and rescale it.\n", + "* Applying quantum phase estimation\n", + " * Use Quantum Phase Estimation (QPE) to find the number non-zero eigenvalues of the Laplacian matrix. Round up the results and get the Betti numbers.\n", + " * Vary the resolution threshold and obtain a series of Betti numbers, which are the Betti curves.\n", + "* Detecting financial market crashes\n", + " * Find the relation between Betti numbers and financial market crashes.\n", + " \n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "8a89d505", + "metadata": {}, + "source": [ + "
NOTE:\n", + "\n", + "In the coding process, it is recommended to start with the following initial values for the variables: \n", + "\n", + "* `N = 4` # dimension of vectors\n", + "* `d = 5` # time delay\n", + "* `w = 5` # window size\n", + "* `epsilon = 0.1` # resolution threshold\n", + "* `q = 3` # number of precision qubits\n", + "\n", + "However, you will be tasked with determining the optimal values later in this challenge.\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "1656ba25", + "metadata": {}, + "source": [ + "### Step 0: Loading data\n", + "\n", + "\n", + "To assess the practical applicability of TDA with quantum techniques, we will analyze a small dataset of the S&P 500 index from the period surrounding the 2008 financial crisis. You may find the associated file: *SP500.csv*" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "id": "4ec880cd", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
0
01253.7550
11269.8250
21284.1850
31274.1100
41279.9900
......
78776.4250
79834.2050
80857.4500
81864.3525
82889.2825
\n", + "

83 rows × 1 columns

\n", + "
" + ], + "text/plain": [ + " 0\n", + "0 1253.7550\n", + "1 1269.8250\n", + "2 1284.1850\n", + "3 1274.1100\n", + "4 1279.9900\n", + ".. ...\n", + "78 776.4250\n", + "79 834.2050\n", + "80 857.4500\n", + "81 864.3525\n", + "82 889.2825\n", + "\n", + "[83 rows x 1 columns]" + ] + }, + "execution_count": 66, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "df = pd.read_csv(\"sp500_full.csv\", header=None)\n", + "dfsmall=pd.read_csv(\"sp500.csv\", header=None)\n", + "df\n", + "dfsmall\n" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "id": "240232aa-4a72-496c-8ab3-30f6a2aacc5b", + "metadata": {}, + "outputs": [], + "source": [ + "time_series = np.log(df[1]).to_numpy().squeeze()\n", + "time_series_small = np.log(dfsmall[0]).to_numpy().squeeze()" + ] + }, + { + "cell_type": "markdown", + "id": "b4597392", + "metadata": {}, + "source": [ + "### Step 1: Preparing point cloud\n", + "\n", + "**Instruction:**\n", + "\n", + "Consider a time series $X = \\{x_0, x_1, \\ldots, x_{L-1}\\}$ of numerical values of length $L$ as input. We choose and fix an embedded dimension $N$ and a time-delay $d \\ge 1$. Taken's embedding theorem convert this time series into a series of $N$-dimensional time-delay coordinate vectors $Z=\\{z_0, z_1, \\dots, z_{L-1-(N-1)d}\\}$:\n", + "\n", + "$$\n", + "\\begin{align*}\n", + "z_0 =& (x_0, x_d, \\ldots, x_{(N-1)d}),\\\\\n", + "z_1 =& (x_1, x_{1+d}, \\ldots, x_{1+(N-1)d}),\\\\\n", + "\\vdots\\\\\n", + "z_t =& (x_t, x_{t+d}, \\ldots, x_{t+(N-1)d}),\\\\\n", + "\\vdots&\\\\\n", + "z_{L-1-(N-1)d} =& (x_{L-1-(N-1)d}, x_{L-1-(N-2)d}, \\ldots, x_{L-1}).\n", + "\\end{align*}\n", + "$$\n", + "\n", + "To detect qualitative changes along a time series, we apply a sliding window of size $w$ and assess how topological properties change along the sliding window. For a proper size, $w$ needs to fullfill $N \\ll w \\ll L$. The sliding window gives a time-varying point cloud embedded in $\\mathcal{R}^N$:\n", + "\n", + "$$\n", + "Z^t = \\{z_t, z_{t+1}, \\ldots, z_{t+w-1}\\}, \\quad \\text{for } t \\in \\{0, \\ldots, K-1\\}\n", + "$$\n", + "\n", + "**Action:**\n", + "\n", + "Following Takens' embedding theorem, transform the `time_series` into a series of $ N $-dimensional vectors. Afterward, apply a sliding window to these vectors and obtain a time-varying point cloud.\n", + "\n", + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "id": "7b701be6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 3, w = 5, L = 5536\n" + ] + } + ], + "source": [ + "N = 3 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 5 # window size\n", + "\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "Z = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "9376bd0b", + "metadata": {}, + "source": [ + "
\n", + " \n", + "BONUS EXERCISE: \n", + "\n", + "`gtda.time_series.TakensEmbedding` can conduct this transformation. Try avoid using this function and build your own embedding function.\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "9780b90c", + "metadata": {}, + "source": [ + "
NOTE:\n", + "\n", + "From step 2, we present an example originally provided in the appendix of [Khandelwal's and Chandra's paper](https://arxiv.org/abs/2302.09553). This example can be used to verify your code.\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "c945e850", + "metadata": {}, + "source": [ + "### Step 2: Building Laplacian\n", + "\n", + "**Instruction:**\n", + "\n", + "In this step, we are going to use `GUDHI`, a Python package specialized in TDA and and higher dimensional geometry understanding. For detailed instructions on the functions we will use, please refer to [this website](https://gudhi.inria.fr/python/latest/rips_complex_user.html#).\n", + "\n", + "A simplicial complex is constructed on the point cloud using `gudhi.RipsComplex` class, followed by its `create_simplex_tree` method. The resolution threshold `epsilon` is set via the `max_edge_length` parameter. This process identifies the connectivity of the complex within the resolution threshold and produces a simplex tree. The simplex tree serves as a general representation of simplicial complexes. Using its `get_filtration` method, simplicies are retrieved as a collection of lists, where elements are grouped based on their connections. Each dimension up to a specified maximum is represented by its respective collection of lists.\n", + "\n", + "**Example:**\n", + "\n", + "Here is an example of a simplex tree $\\mathcal{K}$ with a maximum dimension of 2. In its zeroth dimension, each point is a connected component; In the first dimension, 6 line segments connect 6 pairs of points $[1, 2], [1, 3], [2, 3], [3, 4], [3, 5], [4, 5]$; In the second dimension, a filled trangle is formed among points $[1 ,2 ,3]$.\n", + "\n", + "$$\n", + "\\mathcal{K} = [[[1], [2], [3], [4], [5]],[[1, 2], [1, 3], [2, 3], [3, 4], [3, 5], [4, 5]], [[1, 2, 3]]]\n", + "$$\n", + "\n", + "**Action:**\n", + "\n", + "Build a simplicial complex by applying functions from `GUDHI` on the point cloud obtained in step 1, and extract its simplex tree. It is recommended to store the simplex tree in a format similar to the example provided, i.e., in the format $[S_0, S_1, S_2, \\dots]$, where $S_i$ represents the set of $i$-simplices.\n", + "\n", + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "id": "026d6b61", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "num 0-simplices: 5\n", + "num 1-simplices: 3\n", + "num 2-simplices: 0\n" + ] + } + ], + "source": [ + "import gudhi\n", + "\n", + "epsilon = 0.03 # maximum edge length\n", + "max_dim = 2 # maximum simplex dimension\n", + "\n", + "all_simplices = []\n", + "\n", + "point_cloud = Z[0]\n", + "\n", + "\n", + " \n", + "def get_simplex_tree(point_cloud, epsilon):\n", + " # Simplicial Complex\n", + " rips = gudhi.RipsComplex(points=point_cloud, max_edge_length=epsilon)\n", + " filtration = rips.create_simplex_tree(max_dimension=max_dim).get_filtration()\n", + "\n", + " # Extract simplices by dimension\n", + " simplex_tree = [[] for _ in range(max_dim + 1)]\n", + " for simplex, filtration_value in filtration:\n", + " if filtration_value <= epsilon:\n", + " dim = len(simplex) - 1\n", + " simplex_tree[dim].append(simplex)\n", + " return simplex_tree\n", + "\n", + "simplex_tree = get_simplex_tree(point_cloud, epsilon)\n", + "\n", + "print(f\"num 0-simplices: {len(simplex_tree[0])}\")\n", + "print(f\"num 1-simplices: {len(simplex_tree[1])}\")\n", + "print(f\"num 2-simplices: {len(simplex_tree[2])}\")\n", + "# for dim, simplices in enumerate(simplex_tree):\n", + "# print(f\"{dim}-simplices: {simplices}\")" + ] + }, + { + "cell_type": "markdown", + "id": "573efefa", + "metadata": {}, + "source": [ + "**Instruction:**\n", + "\n", + "Let $S_k$ be the set of $k$-simplicies in the complex $\\mathcal{K}$ with individual simplicies denoted by $s_k ∈ S_k$ written as $[j_0, j_1, \\dots, j_k]$ where $j_i$ is the $i$-th vertex of $s_k$. Note that the vertices are ordered in ascending fashion in the initial point cloud, and this order is kept throughout. The restricted boundary operator $\\partial_k$ is defined on the $k$-simplicies as:\n", + "\n", + "$$\n", + "\\begin{align*}\n", + "\\partial_k s_k &= \\sum_{t=0}^{k} (-1)^t [v_0, \\dots, v_{t-1}, v_{t+1}, \\dots, v_k]\\\\\n", + "&= \\sum_{t=0}^{k} (-1)^t s_{k-1} (t)\n", + "\\end{align*}\n", + "$$\n", + "\n", + "where $s_{k−1}(t)$ is defined as the lower simplex defined from $s_k$ by leaving out the vertex $v_t$. \n", + "\n", + "**Example:**\n", + "\n", + "In the simplex tree $\\mathcal{K}$ we have 1 2-simplex and 6 1-simplicies. By leaving out vertice $v_0=1$, $v_1=2$, $v_2=3$, we obtain the lower simplex $s_1=[2, 3]$, $s_2=[1, 3]$, $s_3=[1, 2]$, respectively. Therefore, the boundary operator on the 2-simplicies $\\partial_2$ should be a 6-by-1 matrix:\n", + "\n", + "$$\n", + "\\partial_2 =\n", + "\\begin{bmatrix}\n", + "1 \\\\\n", + "-1 \\\\\n", + "1 \\\\\n", + "0 \\\\\n", + "0 \\\\\n", + "0\n", + "\\end{bmatrix}\n", + "$$\n", + "\n", + "In the same way, the boundary operator on the 1-simplicies $\\partial_1$ is:\n", + "\n", + "$$\n", + "\\partial_1 =\n", + "\\begin{bmatrix}\n", + "1 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "-1 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & -1 & -1 & 1 & 1 & 0 \\\\\n", + "0 & 0 & 0 & -1 & 0 & 1 \\\\\n", + "0 & 0 & 0 & 0 & -1 & -1\n", + "\\end{bmatrix}\n", + "$$\n", + "\n", + "**Action:**\n", + "\n", + "Define a function that generates the boundary operator for a specified dimension, using a given simplex tree as input.\n", + "\n", + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "c9a4b17b-188b-4f47-9739-9434451b8e0c", + "metadata": {}, + "outputs": [], + "source": [ + "simplex_tree = [[[1],[2],[3],[4],[5]],[[1,2],[1,3],[2,3],[3,4],[3,5],[4,5]],[[1,2,3]]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6d44b576-fb0b-4a50-aa5e-15018e1fc019", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 76, + "id": "246e41ce", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Boundary 1: (5, 6)\n", + "[[-1 -1 0 0 0 0]\n", + " [ 1 0 -1 0 0 0]\n", + " [ 0 1 1 -1 -1 0]\n", + " [ 0 0 0 1 0 -1]\n", + " [ 0 0 0 0 1 1]]\n", + "Boundary 2: (6, 1)\n", + "[[ 1]\n", + " [-1]\n", + " [ 1]\n", + " [ 0]\n", + " [ 0]\n", + " [ 0]]\n" + ] + } + ], + "source": [ + "def boundary(k, simplex_tree): # geenrates boundary operator C_{k} -> C_{k-1}\n", + " if k == 0:\n", + " return None \n", + " \n", + " sk = simplex_tree[k] # k-simplices\n", + " sk_1 = simplex_tree[k-1] # (k-1)-simplices\n", + " \n", + " boundary = np.zeros((len(sk_1), len(sk)), dtype=int)\n", + " \n", + " for j, simplex in enumerate(sk):\n", + " for i in range(k+1):\n", + " face = simplex[:i] + simplex[i+1:]\n", + " index = sk_1.index(list(face))\n", + " boundary[index, j] = (-1)**i\n", + " \n", + " return boundary\n", + "\n", + "boundary1 = boundary(1, simplex_tree)\n", + "boundary2 = boundary(2, simplex_tree)\n", + "\n", + "print(\"Boundary 1:\", boundary1.shape)\n", + "print(boundary1)\n", + "\n", + "print(\"Boundary 2:\", boundary2.shape)\n", + "print(boundary2)" + ] + }, + { + "cell_type": "markdown", + "id": "81764f0d", + "metadata": {}, + "source": [ + "**Instruction:**\n", + "\n", + "The combinatorial laplacian $\\Delta_k$ is defined as:\n", + "\n", + "$$\n", + "\\Delta_k = \\left( \\partial_k \\right)^\\dagger \\partial_k \n", + "+ \\partial_{k+1} \\left( \\partial_{k+1} \\right)^\\dagger\n", + "$$\n", + "\n", + "The QPE algorithm will be used to estimate the number of zero eigenvalues of the Laplacian matrix. Since its exponential matrix serves as the unitary matrix in this algorithm, it must have dimensions $2^q \\times 2^q$, where $q$ represents the number of target qubits. It is recommanded to pad the combinatorial laplacian $\\Delta_k$ with an identity matrix with $\\tilde{\\lambda}_{max}/2$ in place of ones, where $\\tilde{\\lambda}_{max}$ is the estimate of the maximum eigenvalue of $\\Delta_k$ using the Gershgorin circle theorem ([details](https://mathworld.wolfram.com/GershgorinCircleTheorem.html)), such that:\n", + "\n", + "$$\n", + "\\tilde{\\Delta}_k =\n", + "\\begin{bmatrix}\n", + "\\Delta_k & 0 \\\\\n", + "0 & \\frac{\\widetilde{\\lambda}_{\\text{max}}}{2} \\cdot I_{2q - |S_k|}\n", + "\\end{bmatrix}_{2q \\times 2q}\n", + "$$\n", + "\n", + "where $\\Delta_k$ is the padded combinatorial laplacian and $q = \\lceil \\log_2 |S_k| \\rceil$ is the number of qubits this operator will act on. In QPE, as $2\\pi\\theta$ increases beyond $2\\pi$, the eigenvalues will start repeating due to their periodic form. Thus, $\\theta$ is restricted to $[0, 1)$. As $\\lambda \\to 2\\pi\\theta$ this means that $λ \\in [0, 2\\pi)$. Thus, we need to restrict the eigenvalues of the combinatorial laplacian to this range. This can be achieved by rescaling $\\tilde{\\Delta}_k$ by $\\delta/\\tilde{\\lambda}_{max}$ where $\\delta$ is slightly less than $2\\pi$. Thus, the rescaled matrix $H$ and the unitary marix $U$ for QPE are:\n", + "\n", + "$$\n", + "\\begin{align*}\n", + "H &= \\frac{\\delta}{\\tilde{\\lambda}_k} \\tilde{\\Delta}_k\\\\\n", + "U &= e^{iH}\n", + "\\end{align*}\n", + "$$\n", + "\n", + "**Example:**\n", + "\n", + "In our example, the combinational laplacian is in the form of a $6\\times6$ matrix:\n", + "\n", + "$$\n", + "\\begin{align*}\n", + "\\Delta_1 &= (\\partial_1)^\\dagger \\partial_1 + \\partial_2 (\\partial_2)^\\dagger\\\\\n", + "&=\n", + "\\begin{bmatrix}\n", + "3 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 3 & 0 & -1 & -1 & 0 \\\\\n", + "0 & 0 & 3 & -1 & -1 & 0 \\\\\n", + "0 & -1 & -1 & 2 & 1 & -1 \\\\\n", + "0 & -1 & -1 & 1 & 2 & 1 \\\\\n", + "0 & 0 & 0 & -1 & 1 & 2\n", + "\\end{bmatrix}\n", + "\\end{align*}\n", + "$$\n", + "\n", + "It is padded with $\\tilde{\\lambda}_{max}=6$ and $\\delta=6$ to its nearest power of 2, which is 8 ($q=3$):\n", + "\n", + "$$\n", + "\\begin{align}\n", + "H_1 = \\begin{bmatrix}\n", + "3 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 3 & 0 & -1 & -1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 3 & -1 & -1 & 0 & 0 & 0 \\\\\n", + "0 & -1 & -1 & 2 & 1 & -1 & 0 & 0 \\\\\n", + "0 & -1 & -1 & 1 & 2 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & -1 & 1 & 2 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 3 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 3\n", + "\\end{bmatrix}\n", + "\\end{align}\n", + "$$\n", + "\n", + "**Action:**\n", + "\n", + "Define a function to build the Laplacian, where Define a function that automatically determines whether the input Laplacian matrix requires padding. If padding is needed, the function will pad and rescale the matrix accordingly. Then, build the unitary based on the padded matrix, in the form of a circuit.\n", + "\n", + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "id": "dbf2431a-aa85-41e1-a72c-563afec9c949", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Laplacian: (8, 8)\n", + "[[ 2. -1. -1. 0. 0. 0. 0. 0.]\n", + " [-1. 2. -1. 0. 0. 0. 0. 0.]\n", + " [-1. -1. 4. -1. -1. 0. 0. 0.]\n", + " [ 0. 0. -1. 2. -1. 0. 0. 0.]\n", + " [ 0. 0. -1. -1. 2. 0. 0. 0.]\n", + " [ 0. 0. 0. 0. 0. 4. 0. 0.]\n", + " [ 0. 0. 0. 0. 0. 0. 4. 0.]\n", + " [ 0. 0. 0. 0. 0. 0. 0. 4.]]\n" + ] + } + ], + "source": [ + "from scipy.linalg import expm\n", + "\n", + "def get_laplacian(k, simplex_tree): # Get combinatorial laplacian\n", + " if k == 0:\n", + " boundary_k1 = boundary(k+1, simplex_tree)\n", + " laplacian = boundary_k1 @ boundary_k1.T\n", + " else:\n", + " boundary_k = boundary(k, simplex_tree) # boundary k\n", + " boundary_k1 = boundary(k+1, simplex_tree) # boundary k+1\n", + " laplacian = boundary_k.T @ boundary_k + boundary_k1 @ boundary_k1.T\n", + " \n", + " # padding\n", + " n = laplacian.shape[0]\n", + " q = int(np.ceil(np.log2(n)))\n", + " n_pad = 2**q - n\n", + " lambda_max = max_eigenvalue(laplacian)\n", + " \n", + " padded_laplacian = np.zeros((2**q, 2**q))\n", + " padded_laplacian[:n, :n] = laplacian\n", + " padded_laplacian[n:, n:] = np.eye(n_pad) * (lambda_max/2)\n", + " \n", + " return padded_laplacian\n", + "\n", + "def max_eigenvalue(matrix): # estimate max eigenvalue using Gershgorin circle theorem\n", + " row_sums = np.sum(np.abs(matrix), axis=1)\n", + " return np.max(row_sums)\n", + "\n", + "\n", + "\n", + "def get_unitary(laplacian):\n", + " delta = 2 * np.pi * 7/8\n", + " lambda_max = max_eigenvalue(laplacian)\n", + "\n", + " if np.isnan(lambda_max) or lambda_max == 0:\n", + " lambda_max = 1\n", + " H = delta / lambda_max * laplacian\n", + " U = expm(1j * H)\n", + " return U\n", + "\n", + "k = 0\n", + "laplacian = get_laplacian(k, simplex_tree)\n", + "print(\"Laplacian:\", laplacian.shape)\n", + "print(laplacian)" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "id": "099d53c4-e199-4456-8f73-4dd9808b6f0d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Unitary: (8, 8)\n", + "[[ 0.10970723+0.58504472j 0.58110396-0.29687654j 0.39138807+0.05805694j\n", + " -0.04109963-0.17311255j -0.04109963-0.17311255j 0. +0.j\n", + " 0. +0.j 0. +0.j ]\n", + " [ 0.58110396-0.29687654j 0.10970723+0.58504472j 0.39138807+0.05805694j\n", + " -0.04109963-0.17311255j -0.04109963-0.17311255j 0. +0.j\n", + " 0. +0.j 0. +0.j ]\n", + " [ 0.39138807+0.05805694j 0.39138807+0.05805694j -0.56555227-0.23222774j\n", + " 0.39138807+0.05805694j 0.39138807+0.05805694j 0. +0.j\n", + " 0. +0.j 0. +0.j ]\n", + " [-0.04109963-0.17311255j -0.04109963-0.17311255j 0.39138807+0.05805694j\n", + " 0.10970723+0.58504472j 0.58110396-0.29687654j 0. +0.j\n", + " 0. +0.j 0. +0.j ]\n", + " [-0.04109963-0.17311255j -0.04109963-0.17311255j 0.39138807+0.05805694j\n", + " 0.58110396-0.29687654j 0.10970723+0.58504472j 0. +0.j\n", + " 0. +0.j 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " 0. +0.j 0. +0.j -0.92387953+0.38268343j\n", + " 0. +0.j 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " 0. +0.j 0. +0.j 0. +0.j\n", + " -0.92387953+0.38268343j 0. +0.j ]\n", + " [ 0. +0.j 0. +0.j 0. +0.j\n", + " 0. +0.j 0. +0.j 0. +0.j\n", + " 0. +0.j -0.92387953+0.38268343j]]\n" + ] + } + ], + "source": [ + "\n", + "U = get_unitary(laplacian)\n", + "print(\"Unitary:\", U.shape)\n", + "print(U)" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "73f45de9-8671-45dd-84ff-0544a86b982d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1., 0., 0., 0., 0., 0., 0., 0.],\n", + " [0., 1., 0., 0., 0., 0., 0., 0.],\n", + " [0., 0., 1., 0., 0., 0., 0., 0.],\n", + " [0., 0., 0., 1., 0., 0., 0., 0.],\n", + " [0., 0., 0., 0., 1., 0., 0., 0.],\n", + " [0., 0., 0., 0., 0., 1., 0., 0.],\n", + " [0., 0., 0., 0., 0., 0., 1., 0.],\n", + " [0., 0., 0., 0., 0., 0., 0., 1.]])" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "U = np.eye(8)\n", + "U" + ] + }, + { + "cell_type": "markdown", + "id": "0acfea73", + "metadata": {}, + "source": [ + "### Step 3: Applying QPE\n", + "\n", + "**Instruction:**\n", + "\n", + "The Betti number is the number of zero eigenvalues in the Laplacian ([ref](https://link.springer.com/article/10.1007/PL00009218)). \n", + "\n", + "$$\n", + "\\beta_k = \\dim (\\ker(\\Delta_k))\n", + "$$\n", + "\n", + "The betti curve is then a series of Betti numbers on different resolution threshold `epsilon`.\n", + "\n", + "To estimate the number of zero eigenvalues (nullity) in the padded Laplacian matrix (padding didn't add more zero eigenvalues), QPE algorithm is employed. The fundamental concept is that, if the target qubits start out in the maximally mixed state (shown below), which can be thought of as a random choice of an eigenstate, the proportion of all-zero states among all measured states is equal to the proportion of zero eigenvalues among all eigenvalues. Assume the all-zero state show up for $\\{i|\\tilde{\\theta}_i=0\\}$ times in $\\alpha$ shots, the probability of getting all-zero state $p(0)$ is given by:\n", + "\n", + "$$\n", + "\\begin{align*}\n", + "p(0) &= \\frac{\\left| \\{i \\mid \\tilde{\\theta}_i = 0\\} \\right|}{\\alpha} = \\frac{\\tilde{\\beta}_k}{2^q} \\\\\n", + "\\implies \\tilde{\\beta}_k &= 2^q \\cdot p(0)\n", + "\\end{align*}\n", + "$$\n", + "\n", + "Where $\\tilde{\\beta}_k$ is the estimation of $k$-th Betti number. This estimation is then rounded to the nearest integer to obtain the final result." + ] + }, + { + "cell_type": "markdown", + "id": "fc95fe90", + "metadata": {}, + "source": [ + "\"Description\n" + ] + }, + { + "cell_type": "markdown", + "id": "72511671", + "metadata": {}, + "source": [ + "For your reference, the tutorial of QPE in several major quantum computing libraries are listed below:\n", + "\n", + "* [Qiskit](https://github.com/qiskit-community/qiskit-textbook/blob/main/content/ch-algorithms/quantum-phase-estimation.ipynb)\n", + "* [Pennylane](https://pennylane.ai/qml/demos/tutorial_qpe)\n", + "* [CUDA-Q](https://nvidia.github.io/cuda-quantum/latest/specification/cudaq/examples.html#quantum-phase-estimation:~:text=Quantum%20Phase%20Estimation-,%C2%B6,-C%2B%2B)\n", + "* [Cirq](https://quantumai.google/cirq/experiments/textbook_algorithms#phase_estimation)" + ] + }, + { + "cell_type": "markdown", + "id": "481e000c", + "metadata": {}, + "source": [ + "**Example:**\n", + "\n", + "In our example, the probability of measuring all-zero states is approximately $p(0)=0.137 = \\tilde{\\beta}_k / 2^3 \\implies \\tilde{\\beta}_k = 1.096$, which is then rounded to $1$.\n", + "\n", + "**Action:**\n", + "\n", + "Utilize your preferred quantum computing library to apply QPE for estimating the number of zero eigenvalues in the Laplacian matrix. Note that the exponential of the Laplacian matrix is used as the unitary operator in QPE.\n", + "\n", + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "id": "848ef40c", + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, transpile\n", + "from qiskit_aer import AerSimulator\n", + "from qiskit.circuit.library import QFT\n", + "from qiskit.quantum_info import Operator\n", + "from qiskit.visualization import plot_histogram\n", + "import numpy as np\n", + "import math\n", + "\n", + "pi=np.pi\n", + "\n", + "\n", + "def phase_estimation(oracle, eigenstate, precision):\n", + " n = precision\n", + " \n", + " # Calculate number of target qubits needed from oracle size\n", + " oracle_size = oracle.num_qubits\n", + " \n", + " # Create registers: n counting qubits + oracle_size target qubits + oracle_size auxillary qubits\n", + " qr = QuantumRegister(n + 2*oracle_size, 'q')\n", + " c = ClassicalRegister(n+oracle_size, 'c')\n", + " qc = QuantumCircuit(qr, c)\n", + "\n", + " # Initialize target qubits in maximally entangled state\n", + " # First apply H to first target qubit\n", + " qc.h(n)\n", + " qc.cx(n,n+oracle_size)\n", + " # Then apply CX\n", + " for i in range(oracle_size-1):\n", + " \n", + " qc.h(n + i + 1) # H gate on target qubit\n", + " qc.cx(n + i+1, n + i + oracle_size+1) \n", + " qc.barrier()\n", + "\n", + " \n", + "\n", + " # Apply Hadamard to all counting qubits\n", + " for i in range(n):\n", + " qc.h(i)\n", + "\n", + " # Create controlled version of oracle\n", + " cGate = oracle.control(1)\n", + " qc.barrier()\n", + "\n", + " # Apply controlled operations with proper target qubits\n", + " for i in range(n):\n", + " for j in range(2**i):\n", + " all_qubits = [i] + list(range(n, n + oracle_size))\n", + " qc.append(cGate, all_qubits)\n", + "\n", + " qc.barrier()\n", + " iqft = QFT(n).inverse()\n", + " qc.append(iqft, range(n))\n", + " qc.barrier()\n", + "\n", + " # Measure counting qubits\n", + " for i in range(n):\n", + " qc.measure(i, i)\n", + "\n", + " #Measure auxillary qubits\n", + " for i in range(oracle_size):\n", + " \n", + " qc.measure(n+i+oracle_size,n+i)\n", + "\n", + " # Run with more shots for better statistics\n", + " aersim = AerSimulator(shots=10000)\n", + " circuit_transpile = transpile(qc, aersim, optimization_level=1)\n", + " result = aersim.run(circuit_transpile).result()\n", + " counts = result.get_counts()\n", + " counts=counts\n", + " return counts, qc\n", + "\n", + "def create_gate_from_matrix(matrix):\n", + " \"\"\"\n", + " Create a quantum circuit from a nxn unitary matrix\n", + " \"\"\"\n", + " n = matrix.shape[0]\n", + " n_qubits = int(math.log2(n)) # Calculate number of qubits needed\n", + " #print(f\"Matrix size: {n}x{n}\")\n", + " #print(f\"Number of qubits needed: {n_qubits}\")\n", + " \n", + " # Create circuit with the correct number of qubits\n", + " qc = QuantumCircuit(n_qubits)\n", + " \n", + " # Create list of qubits to apply unitary to\n", + " qubits = list(range(n_qubits))\n", + " #print(f\"Applying unitary to qubits: {qubits}\")\n", + " \n", + " # Create operator and verify its dimension\n", + " op = Operator(matrix)\n", + " #print(f\"Operator dimension: {op.dim}\")\n", + " \n", + " # Apply the unitary\n", + " qc.unitary(op, qubits, label='L')\n", + " \n", + " return n_qubits,qc\n", + "\n", + "def zero_phases(counts, precision, n_qubits):\n", + " \"\"\"\n", + " Analyze phases from measurement results and count zero phases\n", + " \"\"\"\n", + " total_shots = sum(counts.values())\n", + " phases = {}\n", + " zero_phase_count = 0\n", + " zero_bitstring='0'*precision\n", + "\n", + " #print(f\"zero bitsring {zero_bitstring}\")\n", + " for bitstring,count in counts.items():\n", + " length=len(bitstring)\n", + " #print(f\"Counts are {bitstring[-precision:],count}\")\n", + " if bitstring[-precision:] == zero_bitstring: # Only check last precision number of qubits\n", + " zero_phase_count =zero_phase_count+count\n", + "\n", + " #print(f\"Zero counts is {zero_phase_count}\")\n", + " \n", + " hist=plot_histogram(counts,title=\"Phase Estimation\")\n", + " n_shots=10000\n", + " betti=(zero_phase_count*(2**n_qubits)/n_shots) \n", + " #print(f\"Unrounded betti number: {betti}\")\n", + " betti=np.round(zero_phase_count*(2**n_qubits)/n_shots) \n", + " \n", + " return hist,betti\n", + "\n", + "\n", + "def analyze_matrix(matrix, precision=5):\n", + " \"\"\"\n", + " Analyze a matrix using QPE to detect zero eigenvalues\n", + " \"\"\"\n", + " \n", + " # Create gate from matrix\n", + " n_qubits,gate = create_gate_from_matrix(matrix)\n", + " \n", + " # Run phase estimation\n", + " counts,qc = phase_estimation(gate, 1, precision)\n", + " \n", + " # Analyze phases and count zeros\n", + " hist,betti = zero_phases(counts, precision, n_qubits)\n", + " \n", + " # print(f\"\\nResults:\")\n", + " # print(f\"Betti number: {betti}\")\n", + " \n", + " return betti,hist\n", + "\n", + "# print(\"Analyzing matrix:\")\n", + "# hist,betti,qc = analyze_matrix(U)\n", + "\n", + "# hist\n", + "# qc.draw(output='mpl')" + ] + }, + { + "cell_type": "markdown", + "id": "5013deb5-9895-4d18-883a-a2e4936dd12e", + "metadata": {}, + "source": [ + "Bonus\n", + "\n", + "\n", + "1) The all zero state corresponds to the eigenstate corresponding to phase=0 corresponding to eigenvalue=1 of the unitary matrix of interest. In our case U=exp(iL_k) where L_k is the laplacian for k-simplexes. We are interested in calculate the number of zero eigenvalues of the laplacian, hence we are looking for the number of instances of phi=0 eigenstate in our phase estimator.\n", + "\n", + "2) The maximally mixed state corresponds to a equally random mixture of all eigenstates of some operator given that the eigenstates form a complete basis. In the case of the QPE, we use 2q qubits to form a maximally mixed state by tracing out q of the auxillary qubits. While the 2q qubits are in a pure state, the two subsystems of q qubits are in a maximally mixed state. There is no preferred basis for the maximally mixed state, and thus has no bias towards any eigenstates of the unitary matrix whose 0-eigenvalue eigenstate we are estimating. We start with a uniform random mixture of all eigenvectors of the unitary if our starting state is a maximally mixed state.\n", + "\n", + "The parallel state H|0>^*n on the other hand is a uniform superposition of all 2^n bit strings. But this uniform mixture is biased to the computational basis, and the probabilities in the basis of the eigenvectors of the unitary may not be uniform any longer. Thus we might start with a biased distribution of states which more often than not will not be biased to our state of interest i.e the 0-eigenvalue eigenstate, which is one state in a space of 2^n states. Thus we are better off starting with a fully random state like the maximally mixed state.\n", + "\n", + "3) delta schpiel done in slides for better estimation." + ] + }, + { + "cell_type": "markdown", + "id": "f8724ca3", + "metadata": {}, + "source": [ + "
NOTE:\n", + "\n", + "The unitary operator can be constructed by converting the exponential matrix of the Laplacian into a quantum circuit. For instance, in Qiskit, this can be implemented using `circuit.unitary(exp_matrix)`. Alternative methods for constructing the unitary operator will be optionally explored in the **BONUS** section at the end of this notebook.\n", + "
\n", + "
\n", + " \n", + "BONUS EXERCISE: \n", + "\n", + "1. Why we should measure all-zero states?\n", + "2. What is the difference between a maximally mixed state and the $(H\\ket{0})^{\\otimes n}$ state? Two possible aspects are:\n", + "\n", + "* Plotting of their density matrix.\n", + "* Results from QPE.\n", + "\n", + "3. What parameters affect the accuracy of the estimation before rounding? For Laplacian matrices of varying sizes, how does the accuracy depend on these parameters? Within what range of values do these parameters guarantee (or are highly likely to produce) a correct final result?\n", + "
" + ] + }, + { + "cell_type": "markdown", + "id": "1cbe5cf2", + "metadata": {}, + "source": [ + "### Step 4: Detecting market crashes" + ] + }, + { + "cell_type": "markdown", + "id": "7f27e81b", + "metadata": {}, + "source": [ + "**Instruction:**\n", + "\n", + "At this point, we have betti curves for each window across our dataset, and we wish to use this to detect market crashes. One such way is to take the difference between these curves—or the pairwise distance—for successive windows and look for spikes. This can be done with the $L^p$ norm of the betti curve for each window, defined as follows:\n", + "\n", + "$$||x||_p = (\\sum_{n}^{i=1} |x_i|^p)^{1/p}$$\n", + "\n", + "Combining these pairwise distances into a vector, we get a single output curve we can analyze. Experiment with different values of $p$, but a good starting point is the $L^2$ Norm. Using this, it is possible to detect regions where a market crash is occuring. Comparing detected crashes with the price data indicates how accurate the crash detection methodology is ([ref](https://github.com/giotto-ai/stock-market-crashes/blob/master/Stock%20Market%20Crash%20Detection.ipynb)). \n", + "\n", + "**Action:**\n", + "\n", + "Use the $L^p$ norm to create pairwise distance curves for successive windows, and then use the results to define when a crash is occuring. Compare this with your data to see how well it performs. You may find the following classical solver is useful.\n", + "\n", + "**Answer:**" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "id": "700a1375-a1b5-4424-bd1d-0b2b2b7e28d5", + "metadata": {}, + "outputs": [], + "source": [ + "#betti number estimation using quantum phase estimation\n", + "def get_betti_number(point_cloud, epsilon, dim):\n", + " # print(\"Constructing tree\")\n", + " simplex_tree = get_simplex_tree(point_cloud, epsilon)\n", + " # print(f\"num 0-simplices: {len(simplex_tree[0])}\")\n", + " # print(f\"num 1-simplices: {len(simplex_tree[1])}\")\n", + " # print(f\"num 2-simplices: {len(simplex_tree[2])}\")\n", + " if len(simplex_tree[dim]) == 0:\n", + " return 0\n", + " # print(\"Computing laplacian\")\n", + " laplacian = get_laplacian(dim, simplex_tree)\n", + " if laplacian.shape[0] ==1:\n", + " return 1 if abs(laplacian[0][0]) < 1e-9 else 0\n", + " # print(f\"Laplacian: {laplacian.shape}\")\n", + " #print(laplacian)\n", + " # print(\"Computing unitary\")\n", + " unitary = get_unitary(laplacian)\n", + " # print(f\"Unitary: {unitary.shape}\")\n", + " #print(unitary)\n", + " # print(\"Performing QPE\")\n", + " \n", + " betti_number = analyze_matrix(unitary)[0]\n", + " return betti_number" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "id": "3892a905-1e01-49b6-8729-bb7c7d450cd2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 5, w = 30, L = 5536\n", + "32.0\n" + ] + } + ], + "source": [ + "N = 5 # embedding dimension\n", + "d = 2 # time delay\n", + "w = 30 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "print(get_betti_number(point_cloud,0.01,0))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3600544a-6b29-4e97-ae7a-6f17aaa7a677", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 94, + "id": "a56afa9c-e36c-475a-ba2e-c1dcee42f643", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 5, w = 30, L = 5536\n", + "0\n" + ] + } + ], + "source": [ + "N = 5 # embedding dimension\n", + "d = 2 # time delay\n", + "w = 30 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "print(get_betti_number(point_cloud,0.01,1))" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "id": "d29ee3eb-11a9-4c15-84c4-050992e27077", + "metadata": {}, + "outputs": [], + "source": [ + "#betti number estimation using classical methods\n", + "import matplotlib.pyplot as plt\n", + "from ripser import ripser\n", + "\n", + "def classical_betti_solver(point_cloud, epsilon, dim):\n", + " '''Return the Betti number on a given point cloud.\n", + " Args:\n", + " point_cloud: the point cloud after applying the sliding window.\n", + " epsilon: resolution threshold.\n", + " dim: the dimension on which the Betti number is calculated\n", + " '''\n", + " result = ripser(point_cloud, maxdim=dim)\n", + " diagrams = result[\"dgms\"]\n", + " return len(\n", + " [interval for interval in diagrams[dim] if interval[0] < epsilon < interval[1]]\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "id": "8cc84280-84fd-483a-bb6c-4b4e97c46fbb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 5, w = 10, L = 5536\n", + "0\n" + ] + } + ], + "source": [ + "N = 5 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 10 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "print(classical_betti_solver(point_cloud,0.01,1))" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "id": "1a909d85-1aac-44a8-b4bb-682165f58c9d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 5, w = 10, L = 5536\n", + "16.0\n" + ] + } + ], + "source": [ + "N = 5 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 10 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "print(get_betti_number(point_cloud,0.01,0))" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "id": "3a827b21-0242-4017-a649-383d446bf472", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 3, w = 5, L = 5536\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Calculating Betti numbers: 100%|█████████| 3000/3000 [00:00<00:00, 12314.81it/s]\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0EAAAIhCAYAAACIfrE3AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABMQ0lEQVR4nO3deXxU9fX/8fckmWyQAEpYjSARCZRVIhKoCiphUUQpYsEFqdr6FRXh51qxLFqgrriigoJWAYviVhGJIktlUTGICgK1rAoCsiQhkEyS+/uDZkpMgLk3d+7Nzbyej0ceZe7cmXsm/Zjw5nzmjM8wDEMAAAAAECGi3C4AAAAAAJxECAIAAAAQUQhBAAAAACIKIQgAAABARCEEAQAAAIgohCAAAAAAEYUQBAAAACCiEIIAAAAARBRCEAAAAICIQggCgAg2c+ZM+Xy+cl8pKSnq0aOH/vnPf1p+3ueee04zZ86scPynn37SuHHjtGbNmgr3jRs3Tj6fL+RrLFu2TIMHD1bTpk0VGxurOnXqqFu3bpo6daoOHTpkuXYAQM1HCAIAaMaMGVqxYoWWL1+uF198UdHR0erfv7/ef/99S893ohA0fvz4SkPQjTfeqBUrVoT0/GPHjtX555+vH3/8UQ8++KCys7M1Z84cXXTRRRo3bpzGjBljqW4AQGSIcbsAAID72rZtq4yMjODtPn36qF69epo9e7b69+/vSA2nnXaaTjvttJOeN3fuXE2YMEE33HCDpk2bVq571LdvX919990hh6mTKSgoUGJioi3PBQCoPugEAQAqiI+PV2xsrPx+f7njRUVFeuihh5Senq64uDilpKRo+PDh2rNnT/Cc5s2b67vvvtOSJUuCW+yaN2+uxYsX65xzzpEkDR8+PHjfuHHjJIW+HW7ChAmqV6+ennrqqUrPT0pKUlZWliRpy5Yt8vl8lXaljr32sdf/6quvNGjQINWrV09paWmaMmWKfD6f/v3vf1d4jnvuuUexsbHau3dv8NjHH3+siy66SMnJyUpMTFT37t31ySeflHvcnj179Mc//lGpqanB72P37t318ccfn/T1AwCqjhAEAFBJSYmKi4sVCAS0Y8cO3XHHHTp06JCGDh0aPKe0tFQDBgzQ5MmTNXToUH3wwQeaPHmysrOz1aNHDx0+fFiS9Pbbb6tFixbq1KmTVqxYoRUrVujtt9/W2WefrRkzZkiSxowZE7zvxhtvDLnOnTt36ttvv1VWVlbYOjQDBw7UmWeeqblz5+r555/XNddco9jY2ApBqqSkRK+99pr69++v+vXrS5Jee+01ZWVlKTk5Wa+88or+8Y9/6JRTTlHv3r3LBaFrr71W77zzjv7yl79o4cKFmj59ui6++GL98ssvYXlNAIDy2A4HAFDXrl3L3Y6Li9Mzzzyj3r17B4/94x//0IIFC/TWW29p4MCBweMdOnTQOeeco5kzZ+r//u//1KlTJyUkJCg5ObnC87Zt21aSlJaWVuG+UGzbtk2SdMYZZ5h+bKiGDRum8ePHlzt26aWX6pVXXtGECRMUFXX03w8XLlyon376ScOHD5d0dOvcyJEjdemll+rtt98OPrZfv346++yz9ec//1mrVq2SJH322We68cYbddNNNwXPGzBgQNheEwCgPDpBAAC9+uqr+uKLL/TFF1/oww8/1LBhwzRixAg988wzwXP++c9/qm7duurfv7+Ki4uDXx07dlSjRo20ePFi916AjX73u99VODZ8+HDt2LGj3Ha1GTNmqFGjRurbt68kafny5dq3b5+GDRtW7vtTWlqqPn366IsvvghOrevSpYtmzpyphx56SCtXrlQgEHDmxQEAJBGCAACSWrdurYyMDGVkZKhPnz564YUXlJWVpbvvvlsHDhyQJP388886cOBA8L1Cx37t2rWr3PtiwuX000+XJG3evDls12jcuHGFY3379lXjxo2D2/n279+v9957T9ddd52io6MlHf3+SNKgQYMqfH/+9re/yTAM7du3T5L0xhtvaNiwYZo+fboyMzN1yimn6LrrrtOuXbvC9roAAP/DdjgAQKXat2+vjz76SBs3blSXLl1Uv359nXrqqVqwYEGl5yclJYW9psaNG6tdu3ZauHBhSJPb4uPjJUmFhYXljp/ovTeVDVuIjo7Wtddeq6eeekoHDhzQrFmzVFhYGNwKJyn4vqCnn376uFv9GjZsGDx3ypQpmjJlirZt26b33ntP9957r3bv3n3c7y8AwD6EIABApco+yyclJUXS0ffFzJkzRyUlJTr33HNP+Ni4uLjgoIRfH5dU6X2heuCBBzR48GDdfvvtFUZkS1J+fr6WL1+urKwsNWzYUPHx8Vq7dm25c959913T1x0+fLgefvhhzZ49WzNnzlRmZqbS09OD93fv3l11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QTaiEwQA4UcnCACqj+LiYj3wwANKTU1VcnKyevToobVr17pd1kkRggAAnkIIAoDq4+WXX9b06dP15JNPKicnRy1bttRVV11V6bk7d+7U0KFD1apVK0VFRemOO+5wtthjEILCgE4QAIQPI7IBoPpYtGiR+vTpo4EDByotLU2jRo3S999/r3379lU4t7CwUCkpKbr//vvVoUMHF6r9nxhXr17jkH4AINzoBAGICIYhFRS4c+3ExJD/VX/Pnj1KT08P3t65c6ckKbrsDZzHaN68uZ588klJRztIbiIEAQA8hRAEICIUFEi1a7tz7fx8qVatkE41yt4UL2njxo267777lJmZqTp16oSrOlsQgmzEYAQACD9CEABUP/fee68eeeQR+Xw+zZ071+1yTooQBADwFEZkA4gIiYlHOzJuXduk0aNH67LLLtP8+fM1ZMgQvfbaaxo8eLCeeOIJtWnTRr179z7pc5SUlGjo0KGaOXOmEhISrFQeMkKQjQzjaAuIThAAhA+dIAARwecLeUtaddCgQQM1atRIv/3tb7V7924999xzuuSSS/TBBx9o1KhRIT1HdHS0Lr/8ck2bNk233357WOtlOhwAwFOYDgcA1UtxcXG5236/X/Hx8Vq2bJkyMjJMPVevXr30/vvv21lepegEhQGdIAAIHzpBAFC9zJ49W5mZmbrooov09ddfa9asWZowYYIOHDig5OTkcueuWbNGkpSfn689e/ZozZo1io2NVZs2bSRJSUlJ2r9/f9hrJgQBADyFEAQA1Uvr1q31+OOPa8SIEWrUqJFuv/123XrrrdqwYYPmz59f7txOnToF/7x69WrNmjVLzZo105YtWyRJGzZsUPv27cNeMyEIAOAphCAAqF4yMjL07LPPKiqq/Dtt2rRpo7y8PB04cEB169aVVH6kdmVeffVVjRgxIlylBvGeIJsc+/8n2+EAIHwIQQDgHY8++qg2btwY0rklJSU699xz1blz5zBXRScIAOAxjMgGAO9IS0tTWlpaSOdGR0fryiuvDHNFRxGCbEInCACcQScIAKqPRYsWKTc31+0yTGM7HADAUxiRDQCoKkKQTegEAYAz6AQBAKqKEAQA8BRCEACgqghBAABPIQQBAKqKEGQTtsMBgDOYDgcAqCpCEADAU+gEAQCqihBkEzpBAOAMpsMBQPVRXFysBx54QKmpqUpOTlaP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izUDs1gzMIs1A7Oqy5o5WQeoDIMRAAAAAEQUQhAAAACAiEIIsklcXJzGjh2ruLg4t0uBR7BmYBZrBmaxZmAWawZmeXXNeHowAgAAAACYRScIAAAAQEQhBAEAAACIKIQgAAAAABGFEAQAAAAgohCCTuC5557TGWecofj4eHXu3FnLli074flLlixR586dFR8frxYtWuj555+vcM5bb72lNm3aKC4uTm3atNHbb78drvLhArvXzHfffaff/e53at68uXw+n6ZMmRLG6uEGu9fMtGnTdN5556levXqqV6+eLr74Yn3++efhfAlwkN3rZd68ecrIyFDdunVVq1YtdezYUX//+9/D+RLgsHD8XabMnDlz5PP5dPnll9tcNdxk95qZOXOmfD5fha8jR46E82WcnIFKzZkzx/D7/ca0adOMdevWGSNHjjRq1aplbN26tdLz//Of/xiJiYnGyJEjjXXr1hnTpk0z/H6/8eabbwbPWb58uREdHW1MnDjRWL9+vTFx4kQjJibGWLlypVMvC2EUjjXz+eefG3feeacxe/Zso1GjRsYTTzzh0KuBE8KxZoYOHWo8++yzRk5OjrF+/Xpj+PDhRp06dYwdO3Y49bIQJuFYL59++qkxb948Y926dca///1vY8qUKUZ0dLSxYMECp14Wwigca6bMli1bjKZNmxrnnXeeMWDAgDC/EjglHGtmxowZRnJysrFz585yX24jBB1Hly5djJtvvrncsfT0dOPee++t9Py7777bSE9PL3fsT3/6k9G1a9fg7cGDBxt9+vQpd07v3r2N3//+9zZVDTeFY80cq1mzZoSgGibca8YwDKO4uNhISkoyXnnllaoXDFc5sV4MwzA6depkjBkzpmrFoloI15opLi42unfvbkyfPt0YNmwYIagGCceamTFjhlGnTh3ba60qtsNVoqioSKtXr1ZWVla541lZWVq+fHmlj1mxYkWF83v37q0vv/xSgUDghOcc7znhHeFaM6i5nFozBQUFCgQCOuWUU+wpHK5wYr0YhqFPPvlEGzZs0Pnnn29f8XBFONfMhAkTlJKSohtuuMH+wuGacK6Z/Px8NWvWTKeddpouvfRS5eTk2P8CTCIEVWLv3r0qKSlRw4YNyx1v2LChdu3aVeljdu3aVen5xcXF2rt37wnPOd5zwjvCtWZQczm1Zu699141bdpUF198sT2FwxXhXC8HDx5U7dq1FRsbq0suuURPP/20evXqZf+LgKPCtWY+++wzvfTSS5o2bVp4CodrwrVm0tPTNXPmTL333nuaPXu24uPj1b17d23atCk8LyREMa5evZrz+XzlbhuGUeHYyc7/9XGzzwlvCceaQc0WzjXz8MMPa/bs2Vq8eLHi4+NtqBZuC8d6SUpK0po1a5Sfn69PPvlEo0ePVosWLdSjRw/7Codr7FwzeXl5uuaaazRt2jTVr1/f/mJRLdj9c6Zr167q2rVr8P7u3bvr7LPP1tNPP62nnnrKrrJNIwRVon79+oqOjq6Qenfv3l0h7ZZp1KhRpefHxMTo1FNPPeE5x3tOeEe41gxqrnCvmUcffVQTJ07Uxx9/rPbt29tbPBwXzvUSFRWlM888U5LUsWNHrV+/XpMmTSIEeVw41sx3332nLVu2qH///sH7S0tLJUkxMTHasGGD0tLSbH4lcIpTf5eJiorSOeec43oniO1wlYiNjVXnzp2VnZ1d7nh2dra6detW6WMyMzMrnL9w4UJlZGTI7/ef8JzjPSe8I1xrBjVXONfMI488ogcffFALFixQRkaG/cXDcU7+jDEMQ4WFhVUvGq4Kx5pJT0/XN998ozVr1gS/LrvsMvXs2VNr1qxRampq2F4Pws+pnzOGYWjNmjVq3LixPYVb5fwsBm8oGxH40ksvGevWrTPuuOMOo1atWsaWLVsMwzCMe++917j22muD55eNCBw1apSxbt0646WXXqowIvCzzz4zoqOjjcmTJxvr1683Jk+ezIjsGiQca6awsNDIyckxcnJyjMaNGxt33nmnkZOTY2zatMnx1wf7hWPN/O1vfzNiY2ONN998s9wo0ry8PMdfH+wVjvUyceJEY+HChcYPP/xgrF+/3njssceMmJgYY9q0aY6/PtgvHGvm15gOV7OEY82MGzfOWLBggfHDDz8YOTk5xvDhw42YmBhj1apVjr++YxGCTuDZZ581mjVrZsTGxhpnn322sWTJkuB9w4YNMy644IJy5y9evNjo1KmTERsbazRv3tyYOnVqheecO3eu0apVK8Pv9xvp6enGW2+9Fe6XAQfZvWY2b95sSKrw9evngXfZvWaaNWtW6ZoZO3asA68G4Wb3ern//vuNM88804iPjzfq1atnZGZmGnPmzHHipcAh4fi7zLEIQTWP3WvmjjvuME4//XQjNjbWSElJMbKysozly5c78VJOyGcY/333EgAAAABEAN4TBAAAACCiEIIAAAAARBRCEAAAAICIQggCAAAAEFEIQQAAAAAiCiEIAAAAQEQhBAEAAACIKIQgAAAAABGFEAQAcMyGDRvUqFEj5eXlOXbN66+/Xpdffnnwdo8ePXTHHXfYeo0777xTt99+u63PCQAIH0IQAMAx999/v0aMGKGkpCRJ0uLFi+Xz+Sr92rVrly3XfPLJJzVz5kxbnut47r77bs2YMUObN28O63UAAPYgBAEAHLFjxw699957Gj58eIX7NmzYoJ07d5b7atCggS3XrVOnjurWrWvLcx1PgwYNlJWVpeeffz6s1wEA2IMQBACwZOXKlerevbuSkpJUq1YttWvXTl988cVxz//HP/6hDh066LTTTqtwX4MGDdSoUaNyX1FRR39FlW1nGz9+vBo0aKDk5GT96U9/UlFRUfDxb775ptq1a6eEhASdeuqpuvjii3Xo0KFyjz+e/fv367rrrlO9evWUmJiovn37atOmTcH7Z86cqbp16+qjjz5S69atVbt2bfXp00c7d+4s9zyXXXaZZs+eHdL3DgDgLkIQAMCSIUOG6IwzztDnn3+ub7/9VlOmTFHDhg2Pe/7SpUuVkZFh6VqffPKJ1q9fr08//VSzZ8/W22+/rfHjx0uSdu7cqSFDhugPf/iD1q9fr8WLF2vgwIEyDCOk577++uv15Zdf6r333tOKFStkGIb69eunQCAQPKegoECPPvqo/v73v2vp0qXatm2b7rzzznLP06VLF23fvl1bt2619BoBAM6JcbsAAIA3lZSU6PTTT9eZZ54pv9+vM84444Tnb9myRZ07d670vl93h5o2baoNGzYEb8fGxurll19WYmKifvOb32jChAm666679OCDD2rnzp0qLi7WwIED1axZM0lSu3btQnoNmzZt0nvvvafPPvtM3bp1kyS9/vrrSk1N1TvvvKMrr7xSkhQIBPT8888rLS1NknTrrbdqwoQJFWoue51ldQAAqidCEADAknnz5umKK67Qww8/rPj4eP3444+qU6fOcc8/fPiw4uPjK71v2bJlwWEJkhQTU/7XU4cOHZSYmBi8nZmZqfz8fG3fvl0dOnTQRRddpHbt2ql3797KysrSoEGDVK9evZO+hvXr1ysmJkbnnntu8Nipp56qVq1aaf369cFjiYmJwQAkSY0bN9bu3bvLPVdCQoKko10jAED1xnY4AIAl9913n84++2wtX75ca9asKRdiKlO/fn3t37+/0vvOOOMMnXnmmcGv5s2bh1SDz+dTdHS0srOz9eGHH6pNmzZ6+umn1apVq5AmtR1vy5xhGPL5fMHbfr+/wnV//dh9+/ZJklJSUkKqHQDgHkIQAMC0vXv36uOPP9aECRPUpUsXnXnmmcFBBsfTqVMnrVu3ztL1vv76ax0+fDh4e+XKlapdu3ZwG53P51P37t01fvx45eTkKDY2Vm+//fZJn7dNmzYqLi7WqlWrgsd++eUXbdy4Ua1btzZV47fffiu/36/f/OY3ph4HAHAeIQgAYFr9+vWVmpqqv/zlL1q9erW2bt2qxYsXa+HChcd9TO/evbVixQqVlJRUuG/37t3atWtXua9jBxMUFRXphhtu0Lp16/Thhx9q7NixuvXWWxUVFaVVq1Zp4sSJ+vLLL7Vt2zbNmzdPe/bsCSnEtGzZUgMGDNBNN92kf/3rX/r66691zTXXqGnTphowYICp78myZct03nnnBbfFAQCqL0IQAMCSDz/8UKWlperdu7fOOuss3XTTTfr555+Pe36/fv3k9/v18ccfV7ivVatWaty4cbmv1atXB++/6KKL1LJlS51//vkaPHiw+vfvr3HjxkmSkpOTtXTpUvXr109nnXWWxowZo8cee0x9+/YN6XXMmDFDnTt31qWXXqrMzEwZhqH58+dX2AJ3MrNnz9ZNN91k6jEAAHf4jFBniAIAUEXPPfec3n33XX300UchP+b666/XgQMH9M4774SvsCr64IMPdNddd2nt2rUVhjoAAKofflIDABzzxz/+Ufv371deXt5JByl4yaFDhzRjxgwCEAB4BJ0gAEC15oVOEADAWwhBAAAAACIKgxEAAAAARBRCEAAAAICIQggCAAAAEFEIQQAAAAAiCiEIAAAAQEQhBAEAAACIKIQgAAAAABGFEAQAAAAgovx/DlTOBDwxm+oAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Maximum β₍0₎: 5\n", + "Maximum β₍1₎: 1\n", + "Maximum β₍2₎: 0\n" + ] + } + ], + "source": [ + "#classical Betti solver\n", + "import matplotlib.pyplot as plt\n", + "from ripser import ripser\n", + "\n", + "def classical_betti_solver(point_cloud, epsilon, dim):\n", + " '''Return the Betti number on a given point cloud.\n", + " Args:\n", + " point_cloud: the point cloud after applying the sliding window.\n", + " epsilon: resolution threshold.\n", + " dim: the dimension on which the Betti number is calculated\n", + " '''\n", + " result = ripser(point_cloud, maxdim=dim)\n", + " diagrams = result[\"dgms\"]\n", + " return len(\n", + " [interval for interval in diagrams[dim] if interval[0] < epsilon < interval[1]]\n", + " )\n", + "\n", + "# write your code here\n", + "from tqdm import tqdm\n", + "\n", + "N = 3 # embedding dimension\n", + "d = 1 # time delay\n", + "w =5 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "\n", + "# Define ranges\n", + "eps_range = np.linspace(0, 0.05, 1000)\n", + "k_range = [0,1,2] # Calculate for k = 0, 1, and 2\n", + "\n", + "# Dictionary to store Betti numbers for each k\n", + "betti_numbers = {k: [] for k in k_range}\n", + "\n", + "# Calculate Betti numbers for each epsilon and k with progress bar\n", + "total_iterations = len(eps_range) * len(k_range)\n", + "with tqdm(total=total_iterations, desc=\"Calculating Betti numbers\") as pbar:\n", + " for eps in eps_range:\n", + " for k in k_range:\n", + " betti_numbers[k].append(classical_betti_solver(point_cloud, eps, k))\n", + " pbar.update(1)\n", + "\n", + "# Create plot\n", + "plt.figure(figsize=(10, 6))\n", + "colors = ['blue', 'red', 'green'] # One color for each k\n", + "\n", + "# Plot each k dimension\n", + "for k, color in zip(k_range, colors):\n", + " plt.plot(eps_range, betti_numbers[k], \n", + " color=color, \n", + " label=f'β₍{k}₎')\n", + "\n", + "plt.xlabel('ε (Epsilon)')\n", + "plt.ylabel('Betti Number')\n", + "plt.title('Betti Curves')\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "# Print maximum values\n", + "for k in k_range:\n", + " print(f\"Maximum β₍{k}₎: {max(betti_numbers[k])}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ce5ab90-9119-4df0-8fac-67b89f81b01a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 104, + "id": "b4cab0b1-e620-4961-b605-836e0aec5f2f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 3, w = 5, L = 5536\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Calculating Betti numbers: 4%|▌ | 41/1000 [00:01<00:45, 20.95it/s]\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[104], line 43\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m eps \u001b[38;5;129;01min\u001b[39;00m eps_range:\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m k \u001b[38;5;129;01min\u001b[39;00m k_range:\n\u001b[0;32m---> 43\u001b[0m betti_numbers[k]\u001b[38;5;241m.\u001b[39mappend(get_betti_number(point_cloud, eps, k))\n\u001b[1;32m 44\u001b[0m pbar\u001b[38;5;241m.\u001b[39mupdate(\u001b[38;5;241m1\u001b[39m)\n\u001b[1;32m 46\u001b[0m \u001b[38;5;66;03m# Create plot\u001b[39;00m\n", + "Cell \u001b[0;32mIn[89], line 21\u001b[0m, in \u001b[0;36mget_betti_number\u001b[0;34m(point_cloud, epsilon, dim)\u001b[0m\n\u001b[1;32m 16\u001b[0m unitary \u001b[38;5;241m=\u001b[39m get_unitary(laplacian)\n\u001b[1;32m 17\u001b[0m \u001b[38;5;66;03m# print(f\"Unitary: {unitary.shape}\")\u001b[39;00m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;66;03m#print(unitary)\u001b[39;00m\n\u001b[1;32m 19\u001b[0m \u001b[38;5;66;03m# print(\"Performing QPE\")\u001b[39;00m\n\u001b[0;32m---> 21\u001b[0m betti_number \u001b[38;5;241m=\u001b[39m analyze_matrix(unitary)[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 22\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m betti_number\n", + "Cell \u001b[0;32mIn[84], line 133\u001b[0m, in \u001b[0;36manalyze_matrix\u001b[0;34m(matrix, precision)\u001b[0m\n\u001b[1;32m 130\u001b[0m n_qubits,gate \u001b[38;5;241m=\u001b[39m create_gate_from_matrix(matrix)\n\u001b[1;32m 132\u001b[0m \u001b[38;5;66;03m# Run phase estimation\u001b[39;00m\n\u001b[0;32m--> 133\u001b[0m counts,qc \u001b[38;5;241m=\u001b[39m phase_estimation(gate, \u001b[38;5;241m1\u001b[39m, precision)\n\u001b[1;32m 135\u001b[0m \u001b[38;5;66;03m# Analyze phases and count zeros\u001b[39;00m\n\u001b[1;32m 136\u001b[0m hist,betti \u001b[38;5;241m=\u001b[39m zero_phases(counts, precision, n_qubits)\n", + "Cell \u001b[0;32mIn[84], line 66\u001b[0m, in \u001b[0;36mphase_estimation\u001b[0;34m(oracle, eigenstate, precision)\u001b[0m\n\u001b[1;32m 64\u001b[0m \u001b[38;5;66;03m# Run with more shots for better statistics\u001b[39;00m\n\u001b[1;32m 65\u001b[0m aersim \u001b[38;5;241m=\u001b[39m AerSimulator(shots\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m10000\u001b[39m)\n\u001b[0;32m---> 66\u001b[0m circuit_transpile \u001b[38;5;241m=\u001b[39m transpile(qc, aersim, optimization_level\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m)\n\u001b[1;32m 67\u001b[0m result \u001b[38;5;241m=\u001b[39m aersim\u001b[38;5;241m.\u001b[39mrun(circuit_transpile)\u001b[38;5;241m.\u001b[39mresult()\n\u001b[1;32m 68\u001b[0m counts \u001b[38;5;241m=\u001b[39m result\u001b[38;5;241m.\u001b[39mget_counts()\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/utils/deprecation.py:184\u001b[0m, in \u001b[0;36mdeprecate_arg..decorator..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 172\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 173\u001b[0m _maybe_warn_and_rename_kwarg(\n\u001b[1;32m 174\u001b[0m args,\n\u001b[1;32m 175\u001b[0m kwargs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 182\u001b[0m predicate\u001b[38;5;241m=\u001b[39mpredicate,\n\u001b[1;32m 183\u001b[0m )\n\u001b[0;32m--> 184\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/utils/deprecation.py:184\u001b[0m, in \u001b[0;36mdeprecate_arg..decorator..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 172\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 173\u001b[0m _maybe_warn_and_rename_kwarg(\n\u001b[1;32m 174\u001b[0m args,\n\u001b[1;32m 175\u001b[0m kwargs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 182\u001b[0m predicate\u001b[38;5;241m=\u001b[39mpredicate,\n\u001b[1;32m 183\u001b[0m )\n\u001b[0;32m--> 184\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + " \u001b[0;31m[... skipping similar frames: deprecate_arg..decorator..wrapper at line 184 (1 times)]\u001b[0m\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/utils/deprecation.py:184\u001b[0m, in \u001b[0;36mdeprecate_arg..decorator..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 172\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 173\u001b[0m _maybe_warn_and_rename_kwarg(\n\u001b[1;32m 174\u001b[0m args,\n\u001b[1;32m 175\u001b[0m kwargs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 182\u001b[0m predicate\u001b[38;5;241m=\u001b[39mpredicate,\n\u001b[1;32m 183\u001b[0m )\n\u001b[0;32m--> 184\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/compiler/transpiler.py:423\u001b[0m, in \u001b[0;36mtranspile\u001b[0;34m(circuits, backend, basis_gates, inst_map, coupling_map, backend_properties, initial_layout, layout_method, routing_method, translation_method, scheduling_method, instruction_durations, dt, approximation_degree, timing_constraints, seed_transpiler, optimization_level, callback, output_name, unitary_synthesis_method, unitary_synthesis_plugin_config, target, hls_config, init_method, optimization_method, ignore_backend_supplied_default_methods, num_processes, qubits_initially_zero)\u001b[0m\n\u001b[1;32m 411\u001b[0m warnings\u001b[38;5;241m.\u001b[39mfilterwarnings(\n\u001b[1;32m 412\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mignore\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 413\u001b[0m category\u001b[38;5;241m=\u001b[39m\u001b[38;5;167;01mDeprecationWarning\u001b[39;00m,\n\u001b[1;32m 414\u001b[0m message\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.*``instruction_durations`` is deprecated as of Qiskit 1.3.*\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 415\u001b[0m module\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mqiskit\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 416\u001b[0m )\n\u001b[1;32m 417\u001b[0m warnings\u001b[38;5;241m.\u001b[39mfilterwarnings(\n\u001b[1;32m 418\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mignore\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 419\u001b[0m category\u001b[38;5;241m=\u001b[39m\u001b[38;5;167;01mDeprecationWarning\u001b[39;00m,\n\u001b[1;32m 420\u001b[0m message\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.*``backend_properties`` is deprecated as of Qiskit 1.3.*\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 421\u001b[0m module\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mqiskit\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 422\u001b[0m )\n\u001b[0;32m--> 423\u001b[0m pm \u001b[38;5;241m=\u001b[39m generate_preset_pass_manager(\n\u001b[1;32m 424\u001b[0m optimization_level,\n\u001b[1;32m 425\u001b[0m target\u001b[38;5;241m=\u001b[39mtarget,\n\u001b[1;32m 426\u001b[0m backend\u001b[38;5;241m=\u001b[39mbackend,\n\u001b[1;32m 427\u001b[0m basis_gates\u001b[38;5;241m=\u001b[39mbasis_gates,\n\u001b[1;32m 428\u001b[0m coupling_map\u001b[38;5;241m=\u001b[39mcoupling_map,\n\u001b[1;32m 429\u001b[0m instruction_durations\u001b[38;5;241m=\u001b[39minstruction_durations,\n\u001b[1;32m 430\u001b[0m backend_properties\u001b[38;5;241m=\u001b[39mbackend_properties,\n\u001b[1;32m 431\u001b[0m timing_constraints\u001b[38;5;241m=\u001b[39mtiming_constraints,\n\u001b[1;32m 432\u001b[0m inst_map\u001b[38;5;241m=\u001b[39minst_map,\n\u001b[1;32m 433\u001b[0m initial_layout\u001b[38;5;241m=\u001b[39minitial_layout,\n\u001b[1;32m 434\u001b[0m layout_method\u001b[38;5;241m=\u001b[39mlayout_method,\n\u001b[1;32m 435\u001b[0m routing_method\u001b[38;5;241m=\u001b[39mrouting_method,\n\u001b[1;32m 436\u001b[0m translation_method\u001b[38;5;241m=\u001b[39mtranslation_method,\n\u001b[1;32m 437\u001b[0m scheduling_method\u001b[38;5;241m=\u001b[39mscheduling_method,\n\u001b[1;32m 438\u001b[0m approximation_degree\u001b[38;5;241m=\u001b[39mapproximation_degree,\n\u001b[1;32m 439\u001b[0m seed_transpiler\u001b[38;5;241m=\u001b[39mseed_transpiler,\n\u001b[1;32m 440\u001b[0m unitary_synthesis_method\u001b[38;5;241m=\u001b[39munitary_synthesis_method,\n\u001b[1;32m 441\u001b[0m unitary_synthesis_plugin_config\u001b[38;5;241m=\u001b[39munitary_synthesis_plugin_config,\n\u001b[1;32m 442\u001b[0m hls_config\u001b[38;5;241m=\u001b[39mhls_config,\n\u001b[1;32m 443\u001b[0m init_method\u001b[38;5;241m=\u001b[39minit_method,\n\u001b[1;32m 444\u001b[0m optimization_method\u001b[38;5;241m=\u001b[39moptimization_method,\n\u001b[1;32m 445\u001b[0m dt\u001b[38;5;241m=\u001b[39mdt,\n\u001b[1;32m 446\u001b[0m qubits_initially_zero\u001b[38;5;241m=\u001b[39mqubits_initially_zero,\n\u001b[1;32m 447\u001b[0m )\n\u001b[1;32m 449\u001b[0m out_circuits \u001b[38;5;241m=\u001b[39m pm\u001b[38;5;241m.\u001b[39mrun(circuits, callback\u001b[38;5;241m=\u001b[39mcallback, num_processes\u001b[38;5;241m=\u001b[39mnum_processes)\n\u001b[1;32m 451\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m name, circ \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mzip\u001b[39m(output_name, out_circuits):\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/utils/deprecation.py:184\u001b[0m, in \u001b[0;36mdeprecate_arg..decorator..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 172\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 173\u001b[0m _maybe_warn_and_rename_kwarg(\n\u001b[1;32m 174\u001b[0m args,\n\u001b[1;32m 175\u001b[0m kwargs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 182\u001b[0m predicate\u001b[38;5;241m=\u001b[39mpredicate,\n\u001b[1;32m 183\u001b[0m )\n\u001b[0;32m--> 184\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/utils/deprecation.py:184\u001b[0m, in \u001b[0;36mdeprecate_arg..decorator..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 172\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 173\u001b[0m _maybe_warn_and_rename_kwarg(\n\u001b[1;32m 174\u001b[0m args,\n\u001b[1;32m 175\u001b[0m kwargs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 182\u001b[0m predicate\u001b[38;5;241m=\u001b[39mpredicate,\n\u001b[1;32m 183\u001b[0m )\n\u001b[0;32m--> 184\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + " \u001b[0;31m[... skipping similar frames: deprecate_arg..decorator..wrapper at line 184 (1 times)]\u001b[0m\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/utils/deprecation.py:184\u001b[0m, in \u001b[0;36mdeprecate_arg..decorator..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;129m@functools\u001b[39m\u001b[38;5;241m.\u001b[39mwraps(func)\n\u001b[1;32m 172\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mwrapper\u001b[39m(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 173\u001b[0m _maybe_warn_and_rename_kwarg(\n\u001b[1;32m 174\u001b[0m args,\n\u001b[1;32m 175\u001b[0m kwargs,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 182\u001b[0m predicate\u001b[38;5;241m=\u001b[39mpredicate,\n\u001b[1;32m 183\u001b[0m )\n\u001b[0;32m--> 184\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m func(\u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py:333\u001b[0m, in \u001b[0;36mgenerate_preset_pass_manager\u001b[0;34m(optimization_level, backend, target, basis_gates, inst_map, coupling_map, instruction_durations, backend_properties, timing_constraints, initial_layout, layout_method, routing_method, translation_method, scheduling_method, approximation_degree, seed_transpiler, unitary_synthesis_method, unitary_synthesis_plugin_config, hls_config, init_method, optimization_method, dt, qubits_initially_zero, _skip_target)\u001b[0m\n\u001b[1;32m 330\u001b[0m inst_map \u001b[38;5;241m=\u001b[39m _parse_inst_map(inst_map, backend)\n\u001b[1;32m 331\u001b[0m \u001b[38;5;66;03m# The basis gates parser will set _skip_target to True if a custom basis gate is found\u001b[39;00m\n\u001b[1;32m 332\u001b[0m \u001b[38;5;66;03m# (known edge case).\u001b[39;00m\n\u001b[0;32m--> 333\u001b[0m basis_gates, name_mapping, _skip_target \u001b[38;5;241m=\u001b[39m _parse_basis_gates(\n\u001b[1;32m 334\u001b[0m basis_gates, backend, inst_map, _skip_target\n\u001b[1;32m 335\u001b[0m )\n\u001b[1;32m 336\u001b[0m coupling_map \u001b[38;5;241m=\u001b[39m _parse_coupling_map(coupling_map, backend)\n\u001b[1;32m 338\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m target \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py:496\u001b[0m, in \u001b[0;36m_parse_basis_gates\u001b[0;34m(basis_gates, backend, inst_map, skip_target)\u001b[0m\n\u001b[1;32m 492\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mlist\u001b[39m(instructions), name_mapping, skip_target\n\u001b[1;32m 494\u001b[0m instructions \u001b[38;5;241m=\u001b[39m instructions \u001b[38;5;129;01mor\u001b[39;00m backend\u001b[38;5;241m.\u001b[39moperation_names\n\u001b[1;32m 495\u001b[0m name_mapping\u001b[38;5;241m.\u001b[39mupdate(\n\u001b[0;32m--> 496\u001b[0m {name: backend\u001b[38;5;241m.\u001b[39mtarget\u001b[38;5;241m.\u001b[39moperation_from_name(name) \u001b[38;5;28;01mfor\u001b[39;00m name \u001b[38;5;129;01min\u001b[39;00m backend\u001b[38;5;241m.\u001b[39moperation_names}\n\u001b[1;32m 497\u001b[0m )\n\u001b[1;32m 499\u001b[0m \u001b[38;5;66;03m# Check for custom instructions before removing calibrations\u001b[39;00m\n\u001b[1;32m 500\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m inst \u001b[38;5;129;01min\u001b[39;00m instructions:\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit_aer/backends/aerbackend.py:262\u001b[0m, in \u001b[0;36mAerBackend.target\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 259\u001b[0m properties \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mproperties()\n\u001b[1;32m 261\u001b[0m \u001b[38;5;66;03m# Load Qiskit object representation\u001b[39;00m\n\u001b[0;32m--> 262\u001b[0m qiskit_inst_mapping \u001b[38;5;241m=\u001b[39m get_standard_gate_name_mapping()\n\u001b[1;32m 263\u001b[0m qiskit_inst_mapping\u001b[38;5;241m.\u001b[39mupdate(NAME_MAPPING)\n\u001b[1;32m 265\u001b[0m qiskit_control_flow_mapping \u001b[38;5;241m=\u001b[39m {\n\u001b[1;32m 266\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mif_else\u001b[39m\u001b[38;5;124m\"\u001b[39m: IfElseOp,\n\u001b[1;32m 267\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mwhile_loop\u001b[39m\u001b[38;5;124m\"\u001b[39m: WhileLoopOp,\n\u001b[1;32m 268\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfor_loop\u001b[39m\u001b[38;5;124m\"\u001b[39m: ForLoopOp,\n\u001b[1;32m 269\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mswitch_case\u001b[39m\u001b[38;5;124m\"\u001b[39m: SwitchCaseOp,\n\u001b[1;32m 270\u001b[0m }\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/circuit/library/standard_gates/__init__.py:96\u001b[0m, in \u001b[0;36mget_standard_gate_name_mapping\u001b[0;34m()\u001b[0m\n\u001b[1;32m 81\u001b[0m time \u001b[38;5;241m=\u001b[39m Parameter(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mt\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 83\u001b[0m \u001b[38;5;66;03m# Standard gates library mapping, multicontrolled gates not included since they're\u001b[39;00m\n\u001b[1;32m 84\u001b[0m \u001b[38;5;66;03m# variable width\u001b[39;00m\n\u001b[1;32m 85\u001b[0m gates \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 86\u001b[0m IGate(),\n\u001b[1;32m 87\u001b[0m SXGate(),\n\u001b[1;32m 88\u001b[0m XGate(),\n\u001b[1;32m 89\u001b[0m CXGate(),\n\u001b[1;32m 90\u001b[0m RZGate(lambda_),\n\u001b[1;32m 91\u001b[0m RGate(theta, phi),\n\u001b[1;32m 92\u001b[0m C3SXGate(),\n\u001b[1;32m 93\u001b[0m CCXGate(),\n\u001b[1;32m 94\u001b[0m DCXGate(),\n\u001b[1;32m 95\u001b[0m CHGate(),\n\u001b[0;32m---> 96\u001b[0m CPhaseGate(theta),\n\u001b[1;32m 97\u001b[0m CRXGate(theta),\n\u001b[1;32m 98\u001b[0m CRYGate(theta),\n\u001b[1;32m 99\u001b[0m CRZGate(theta),\n\u001b[1;32m 100\u001b[0m CSwapGate(),\n\u001b[1;32m 101\u001b[0m CSXGate(),\n\u001b[1;32m 102\u001b[0m CUGate(theta, phi, lambda_, gamma),\n\u001b[1;32m 103\u001b[0m CU1Gate(lambda_),\n\u001b[1;32m 104\u001b[0m CU3Gate(theta, phi, lambda_),\n\u001b[1;32m 105\u001b[0m CYGate(),\n\u001b[1;32m 106\u001b[0m CZGate(),\n\u001b[1;32m 107\u001b[0m CCZGate(),\n\u001b[1;32m 108\u001b[0m GlobalPhaseGate(theta),\n\u001b[1;32m 109\u001b[0m HGate(),\n\u001b[1;32m 110\u001b[0m PhaseGate(theta),\n\u001b[1;32m 111\u001b[0m RCCXGate(),\n\u001b[1;32m 112\u001b[0m RC3XGate(),\n\u001b[1;32m 113\u001b[0m RXGate(theta),\n\u001b[1;32m 114\u001b[0m RXXGate(theta),\n\u001b[1;32m 115\u001b[0m RYGate(theta),\n\u001b[1;32m 116\u001b[0m RYYGate(theta),\n\u001b[1;32m 117\u001b[0m RZZGate(theta),\n\u001b[1;32m 118\u001b[0m RZXGate(theta),\n\u001b[1;32m 119\u001b[0m XXMinusYYGate(theta, beta),\n\u001b[1;32m 120\u001b[0m XXPlusYYGate(theta, beta),\n\u001b[1;32m 121\u001b[0m ECRGate(),\n\u001b[1;32m 122\u001b[0m SGate(),\n\u001b[1;32m 123\u001b[0m SdgGate(),\n\u001b[1;32m 124\u001b[0m CSGate(),\n\u001b[1;32m 125\u001b[0m CSdgGate(),\n\u001b[1;32m 126\u001b[0m SwapGate(),\n\u001b[1;32m 127\u001b[0m iSwapGate(),\n\u001b[1;32m 128\u001b[0m SXdgGate(),\n\u001b[1;32m 129\u001b[0m TGate(),\n\u001b[1;32m 130\u001b[0m TdgGate(),\n\u001b[1;32m 131\u001b[0m UGate(theta, phi, lambda_),\n\u001b[1;32m 132\u001b[0m U1Gate(lambda_),\n\u001b[1;32m 133\u001b[0m U2Gate(phi, lambda_),\n\u001b[1;32m 134\u001b[0m U3Gate(theta, phi, lambda_),\n\u001b[1;32m 135\u001b[0m YGate(),\n\u001b[1;32m 136\u001b[0m ZGate(),\n\u001b[1;32m 137\u001b[0m Delay(time),\n\u001b[1;32m 138\u001b[0m Reset(),\n\u001b[1;32m 139\u001b[0m Measure(),\n\u001b[1;32m 140\u001b[0m ]\n\u001b[1;32m 141\u001b[0m name_mapping \u001b[38;5;241m=\u001b[39m {gate\u001b[38;5;241m.\u001b[39mname: gate \u001b[38;5;28;01mfor\u001b[39;00m gate \u001b[38;5;129;01min\u001b[39;00m gates}\n\u001b[1;32m 142\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m name_mapping\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/circuit/library/standard_gates/p.py:216\u001b[0m, in \u001b[0;36mCPhaseGate.__init__\u001b[0;34m(self, theta, label, ctrl_state, duration, unit, _base_label)\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\n\u001b[1;32m 206\u001b[0m \u001b[38;5;28mself\u001b[39m,\n\u001b[1;32m 207\u001b[0m theta: ParameterValueType,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 213\u001b[0m _base_label\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 214\u001b[0m ):\n\u001b[1;32m 215\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Create new CPhase gate.\"\"\"\u001b[39;00m\n\u001b[0;32m--> 216\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m(\n\u001b[1;32m 217\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcp\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 218\u001b[0m \u001b[38;5;241m2\u001b[39m,\n\u001b[1;32m 219\u001b[0m [theta],\n\u001b[1;32m 220\u001b[0m num_ctrl_qubits\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m,\n\u001b[1;32m 221\u001b[0m label\u001b[38;5;241m=\u001b[39mlabel,\n\u001b[1;32m 222\u001b[0m ctrl_state\u001b[38;5;241m=\u001b[39mctrl_state,\n\u001b[1;32m 223\u001b[0m base_gate\u001b[38;5;241m=\u001b[39mPhaseGate(theta, label\u001b[38;5;241m=\u001b[39m_base_label),\n\u001b[1;32m 224\u001b[0m duration\u001b[38;5;241m=\u001b[39mduration,\n\u001b[1;32m 225\u001b[0m unit\u001b[38;5;241m=\u001b[39munit,\n\u001b[1;32m 226\u001b[0m )\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/circuit/controlledgate.py:106\u001b[0m, in \u001b[0;36mControlledGate.__init__\u001b[0;34m(self, name, num_qubits, params, label, num_ctrl_qubits, definition, ctrl_state, base_gate, duration, unit, _base_label)\u001b[0m\n\u001b[1;32m 104\u001b[0m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m(name, num_qubits, params, label\u001b[38;5;241m=\u001b[39mlabel, duration\u001b[38;5;241m=\u001b[39mduration, unit\u001b[38;5;241m=\u001b[39munit)\n\u001b[1;32m 105\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_ctrl_qubits \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m--> 106\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mnum_ctrl_qubits \u001b[38;5;241m=\u001b[39m num_ctrl_qubits\n\u001b[1;32m 107\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdefinition \u001b[38;5;241m=\u001b[39m copy\u001b[38;5;241m.\u001b[39mdeepcopy(definition)\n\u001b[1;32m 108\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_ctrl_state \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n", + "File \u001b[0;32m/opt/anaconda3/lib/python3.12/site-packages/qiskit/circuit/controlledgate.py:178\u001b[0m, in \u001b[0;36mControlledGate.num_ctrl_qubits\u001b[0;34m(self, num_ctrl_qubits)\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Get number of control qubits.\u001b[39;00m\n\u001b[1;32m 172\u001b[0m \n\u001b[1;32m 173\u001b[0m \u001b[38;5;124;03m Returns:\u001b[39;00m\n\u001b[1;32m 174\u001b[0m \u001b[38;5;124;03m int: The number of control qubits for the gate.\u001b[39;00m\n\u001b[1;32m 175\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 176\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_num_ctrl_qubits\n\u001b[0;32m--> 178\u001b[0m \u001b[38;5;129m@num_ctrl_qubits\u001b[39m\u001b[38;5;241m.\u001b[39msetter\n\u001b[1;32m 179\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mnum_ctrl_qubits\u001b[39m(\u001b[38;5;28mself\u001b[39m, num_ctrl_qubits):\n\u001b[1;32m 180\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"Set the number of control qubits.\u001b[39;00m\n\u001b[1;32m 181\u001b[0m \n\u001b[1;32m 182\u001b[0m \u001b[38;5;124;03m Args:\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[38;5;124;03m CircuitError: ``num_ctrl_qubits`` is not an integer in ``[1, num_qubits]``.\u001b[39;00m\n\u001b[1;32m 187\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[1;32m 188\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m num_ctrl_qubits \u001b[38;5;241m!=\u001b[39m \u001b[38;5;28mint\u001b[39m(num_ctrl_qubits):\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "#classical Betti solver\n", + "import matplotlib.pyplot as plt\n", + "from ripser import ripser\n", + "\n", + "def classical_betti_solver(point_cloud, epsilon, dim):\n", + " '''Return the Betti number on a given point cloud.\n", + " Args:\n", + " point_cloud: the point cloud after applying the sliding window.\n", + " epsilon: resolution threshold.\n", + " dim: the dimension on which the Betti number is calculated\n", + " '''\n", + " result = ripser(point_cloud, maxdim=dim)\n", + " diagrams = result[\"dgms\"]\n", + " return len(\n", + " [interval for interval in diagrams[dim] if interval[0] < epsilon < interval[1]]\n", + " )\n", + "\n", + "# write your code here\n", + "from tqdm import tqdm\n", + "\n", + "N = 3 # embedding dimension\n", + "d = 1 # time delay\n", + "w =5 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "\n", + "# Define ranges\n", + "eps_range = np.linspace(0, 0.05, 1000)\n", + "k_range = [0] # Calculate for k = 0, 1, and 2\n", + "\n", + "# Dictionary to store Betti numbers for each k\n", + "betti_numbers = {k: [] for k in k_range}\n", + "\n", + "# Calculate Betti numbers for each epsilon and k with progress bar\n", + "total_iterations = len(eps_range) * len(k_range)\n", + "with tqdm(total=total_iterations, desc=\"Calculating Betti numbers\") as pbar:\n", + " for eps in eps_range:\n", + " for k in k_range:\n", + " betti_numbers[k].append(get_betti_number(point_cloud, eps, k))\n", + " pbar.update(1)\n", + "\n", + "# Create plot\n", + "plt.figure(figsize=(10, 6))\n", + "colors = ['blue', 'red', 'green'] # One color for each k\n", + "\n", + "# Plot each k dimension\n", + "for k, color in zip(k_range, colors):\n", + " plt.plot(eps_range, betti_numbers[k], \n", + " color=color, \n", + " label=f'β₍{k}₎')\n", + "\n", + "plt.xlabel('ε (Epsilon)')\n", + "plt.ylabel('Betti Number')\n", + "plt.title('Betti Curves')\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "# Print maximum values\n", + "for k in k_range:\n", + " print(f\"Maximum β₍{k}₎: {max(betti_numbers[k])}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 106, + "id": "d9943731-d546-43a2-8f3d-d226d7d79e5e", + "metadata": {}, + "outputs": [], + "source": [ + "#quantum betti solver\n", + "\n", + "def get_betti_number(point_cloud, epsilon, dim):\n", + " # print(\"Constructing tree\")\n", + " simplex_tree = get_simplex_tree(point_cloud, epsilon)\n", + " # print(f\"num 0-simplices: {len(simplex_tree[0])}\")\n", + " # print(f\"num 1-simplices: {len(simplex_tree[1])}\")\n", + " # print(f\"num 2-simplices: {len(simplex_tree[2])}\")\n", + " if len(simplex_tree[dim]) == 0:\n", + " return 0\n", + " # print(\"Computing laplacian\")\n", + " laplacian = get_laplacian(dim, simplex_tree)\n", + " if laplacian.shape[0] ==1:\n", + " return 1 if abs(laplacian[0][0]) < 1e-9 else 0\n", + " # print(f\"Laplacian: {laplacian.shape}\")\n", + " print(laplacian)\n", + " # print(\"Computing unitary\")\n", + " unitary = get_unitary(laplacian)\n", + " # print(f\"Unitary: {unitary.shape}\")\n", + " # print(unitary)\n", + " # print(\"Performing QPE\")\n", + " betti_number = analyze_matrix(unitary)[0]\n", + " return betti_number" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a0df25c-2832-4b19-8898-0dd29355f3b0", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 109, + "id": "18de4e5a-8e1b-456c-a9ae-6c3e2422c868", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 10, w = 50, L = 5536\n" + ] + } + ], + "source": [ + "from tqdm import tqdm\n", + "\n", + "N = 10 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 50 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "id": "246c0cb5-20c7-4455-a90e-9cf489928669", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "N = 10, w = 50, L = 5536\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Calculating Betti numbers: 100%|██████████| 3000/3000 [00:02<00:00, 1112.23it/s]\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA0oAAAIhCAYAAABwnkrAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAABZjUlEQVR4nO3deXhU5d3G8XsymWyQEJAsgGGLEaQsIlEIVMAlYVFcqMsLLkjV2ooCUkuhaAnUN1iqiBXFCgpaBVqrqH1FTFxYKqCAIAiI1AKiEhNkyZ5MkvP+MZ2RJCwzycycmcn3c11zzcyZM3N+Ex+BO7/nPMdiGIYhAAAAAIBLmNkFAAAAAECgISgBAAAAQD0EJQAAAACoh6AEAAAAAPUQlAAAAACgHoISAAAAANRDUAIAAACAeghKAAAAAFAPQQkAAAAA6iEoAQDOaOnSpbJYLHVuCQkJGjp0qP7v//6v0Z/7zDPPaOnSpQ22f/fdd8rOztb27dsbvJadnS2LxeL2MdavX6+bbrpJHTp0UEREhFq1aqWBAwdq4cKFKi0tbXTtAIDQR1ACALhlyZIl2rhxozZs2KDnnntOVqtVo0aN0j//+c9Gfd6ZgtKsWbNOGZTuuusubdy40a3PnzlzpgYPHqxvv/1Wf/jDH5SXl6cVK1boiiuuUHZ2th566KFG1Q0AaB7CzS4AABAcevbsqfT0dNfz4cOHq3Xr1lq+fLlGjRrllxrOPfdcnXvuuWfd79VXX9Xs2bN15513atGiRXW6UCNGjNDUqVPdDlxnU1ZWppiYGK98FgAgcNBRAgA0SlRUlCIiImSz2epsr6qq0iOPPKLu3bsrMjJSCQkJGj9+vAoLC137dO7cWbt27dLatWtd0/k6d+6sNWvW6OKLL5YkjR8/3vVadna2JPen3s2ePVutW7fWn//851PuHxsbq6ysLEnSgQMHZLFYTtndOvnYJx//008/1Q033KDWrVsrNTVV8+fPl8Vi0b///e8Gn/Hb3/5WEREROnLkiGvbe++9pyuuuEJxcXGKiYnRoEGD9P7779d5X2FhoX7xi18oJSXF9XMcNGiQ3nvvvbN+fwBA0xGUAABuqampUXV1tex2u7755htNnjxZpaWlGjt2rGuf2tpaXXvttXr00Uc1duxYvf3223r00UeVl5enoUOHqry8XJK0cuVKde3aVX379tXGjRu1ceNGrVy5UhdddJGWLFkiSXrooYdcr911111u13n48GF9/vnnysrK8lmnZ/To0TrvvPP06quv6tlnn9Wtt96qiIiIBmGrpqZGL7/8skaNGqW2bdtKkl5++WVlZWUpLi5OL774ov7+97+rTZs2GjZsWJ2wdNttt+mNN97Q73//e+Xm5mrx4sW68sor9cMPP/jkOwEA6mLqHQDALQMGDKjzPDIyUgsWLNCwYcNc2/7+979r9erVeu211zR69GjX9j59+ujiiy/W0qVL9atf/Up9+/ZVdHS04uLiGnxuz549JUmpqakNXnPH119/LUnq0qWLx+9117hx4zRr1qw6266++mq9+OKLmj17tsLCHL+HzM3N1Xfffafx48dLckzTmzRpkq6++mqtXLnS9d6RI0fqoosu0u9+9zt9/PHHkqSPPvpId911l+6++27Xftdee63PvhMAoC46SgAAt7z00kvavHmzNm/erHfeeUfjxo3ThAkTtGDBAtc+//d//6f4+HiNGjVK1dXVrtuFF16o5ORkrVmzxrwv4EU/+9nPGmwbP368vvnmmzpT45YsWaLk5GSNGDFCkrRhwwYdPXpU48aNq/Pzqa2t1fDhw7V582bXanyXXHKJli5dqkceeUSbNm2S3W73z5cDAEgiKAEA3HTBBRcoPT1d6enpGj58uP7yl78oKytLU6dO1fHjxyVJ33//vY4fP+46d+nkW35+fp3zdHylY8eOkqT9+/f77Bjt2rVrsG3EiBFq166da+rgsWPH9NZbb+n222+X1WqV5Pj5SNINN9zQ4Ofzxz/+UYZh6OjRo5Kkv/3tbxo3bpwWL16sjIwMtWnTRrfffrvy8/N99r0AAD9i6h0AoNF69+6td999V19++aUuueQStW3bVuecc45Wr159yv1jY2N9XlO7du3Uq1cv5ebmurUiXVRUlCSpsrKyzvYznQt0qgUirFarbrvtNv35z3/W8ePHtWzZMlVWVrqm3Ulynaf01FNPnXZaYVJSkmvf+fPna/78+fr666/11ltvadq0aSooKDjtzxcA4D0EJQBAozmvdZSQkCDJcZ7OihUrVFNTo/79+5/xvZGRka7FHepvl3TK19z18MMP66abbtLEiRMbLA8uSSUlJdqwYYOysrKUlJSkqKgo7dixo84+b775psfHHT9+vObOnavly5dr6dKlysjIUPfu3V2v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+/fv9+lxAADeQVACAASMb775Rm+99ZbGjx/f4LW9e/fq8OHDdW6JiYleOW6rVq0UHx/vlc86ncTERGVlZenZZ5/16XEAAN5BUAIA+MymTZs0aNAgxcbGqkWLFurVq5c2b9582v3//ve/q0+fPjr33HMbvJaYmKjk5OQ6t7Awx19jzqlzs2bNUmJiouLi4nTPPfeoqqrK9f5//OMf6tWrl6Kjo3XOOefoyiuvVGlpaZ33n86xY8d0++23q3Xr1oqJidGIESO0b98+1+tLly5VfHy83n33XV1wwQVq2bKlhg8frsOHD9f5nGuuuUbLly9362cHADAXQQkA4DNjxoxRly5d9Mknn+jzzz/X/PnzlZSUdNr9161bp/T09EYd6/3339eePXv04Ycfavny5Vq5cqVmzZolSTp8+LDGjBmjn//859qzZ4/WrFmj0aNHyzAMtz77jjvu0JYtW/TWW29p48aNMgxDI0eOlN1ud+1TVlamxx57TH/961+1bt06ff3113rwwQfrfM4ll1yiQ4cO6eDBg436jgAA/wk3uwAAQOiqqalRx44ddd5558lms6lLly5n3P/AgQPq16/fKV+r32Xq0KGD9u7d63oeERGhF154QTExMfrJT36i2bNn6ze/+Y3+8Ic/6PDhw6qurtbo0aPVqVMnSVKvXr3c+g779u3TW2+9pY8++kgDBw6UJL3yyitKSUnRG2+8oRtvvFGSZLfb9eyzzyo1NVWSdN9992n27NkNanZ+T2cdAIDARFACAPjM66+/ruuvv15z585VVFSUvv32W7Vq1eq0+5eXlysqKuqUr61fv961wIMkhYfX/SusT58+iomJcT3PyMhQSUmJDh06pD59+uiKK65Qr169NGzYMGVlZemGG25Q69atz/od9uzZo/DwcPXv39+17ZxzzlG3bt20Z88e17aYmBhXSJKkdu3aqaCgoM5nRUdHS3J0nwAAgY2pdwAAn5k+fbouuugibdiwQdu3b68TdE6lbdu2Onbs2Clf69Kli8477zzXrXPnzm7VYLFYZLValZeXp3feeUc9evTQU089pW7durm1At3ppucZhiGLxeJ6brPZGhy3/nuPHj0qSUpISHCrdgCAeQhKAACfOHLkiN577z3Nnj1bl1xyic477zzX4gun07dvX+3evbtRx/vss89UXl7uer5p0ya1bNnSNWXPYrFo0KBBmjVrlrZt26aIiAitXLnyrJ/bo0cPVVdX6+OPP3Zt++GHH/Tll1/qggsu8KjGzz//XDabTT/5yU88eh8AwP8ISgAAn2jbtq1SUlL0+9//Xlu3btXBgwe1Zs0a5ebmnvY9w4YN08aNG1VTU9PgtYKCAuXn59e5nbyYQlVVle68807t3r1b77zzjmbOnKn77rtPYWFh+vjjj5WTk6MtW7bo66+/1uuvv67CwkK3gk5aWpquvfZa3X333frXv/6lzz77TLfeeqs6dOiga6+91qOfyfr163XppZe6puABAAIXQQkA4DPvvPOOamtrNWzYMJ1//vm6++679f333592/5EjR8pms+m9995r8Fq3bt3Url27OretW7e6Xr/iiiuUlpamwYMH66abbtKoUaOUnZ0tSYqLi9O6des0cuRInX/++XrooYf0+OOPa8SIEW59jyVLlqhfv366+uqrlZGRIcMwtGrVqgbT7c5m+fLluvvuuz16DwDAHBbD3bVRAQDwg2eeeUZvvvmm3n33Xbffc8cdd+j48eN64403fFdYE7399tv6zW9+ox07djRYiAIAEHj4kxoAEFB+8Ytf6NixYyouLj7r4g/BpLS0VEuWLCEkAUCQoKMEAAh6wdBRAgAEF4ISAAAAANTDYg4AAAAAUA9BCQAAAADqISgBAAAAQD0EJQAAAACoh6AEAAAAAPUQlAAAAACgHoISAAAAANRDUAIAAACAev4fS+bmGEmYY+MAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Maximum β₍0₎: 50\n", + "Maximum β₍1₎: 1\n", + "Maximum β₍2₎: 0\n" + ] + } + ], + "source": [ + "\n", + "N = 10 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 50 # window size\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")\n", + "point_cloud = point_clouds[0]\n", + "\n", + "# Define ranges\n", + "eps_range = np.linspace(0, 0.05, 1000)\n", + "k_range = [0,1,2] # Calculate for k = 0, 1, and 2\n", + "\n", + "# Dictionary to store Betti numbers for each k\n", + "betti_numbers = {k: [] for k in k_range}\n", + "\n", + "# Calculate Betti numbers for each epsilon and k with progress bar\n", + "total_iterations = len(eps_range) * len(k_range)\n", + "with tqdm(total=total_iterations, desc=\"Calculating Betti numbers\") as pbar:\n", + " for eps in eps_range:\n", + " for k in k_range:\n", + " betti_numbers[k].append(classical_betti_solver(point_cloud, eps, k))\n", + " pbar.update(1)\n", + "\n", + "# Create plot\n", + "plt.figure(figsize=(10, 6))\n", + "colors = ['blue', 'red', 'green'] # One color for each k\n", + "\n", + "# Plot each k dimension\n", + "for k, color in zip(k_range, colors):\n", + " plt.plot(eps_range, betti_numbers[k], \n", + " color=color, \n", + " label=f'β₍{k}₎')\n", + "\n", + "plt.xlabel('ε (Epsilon)')\n", + "plt.ylabel('Betti Number')\n", + "plt.title('Betti Curves')\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.show()\n", + "\n", + "# Print maximum values\n", + "for k in k_range:\n", + " print(f\"Maximum β₍{k}₎: {max(betti_numbers[k])}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "id": "81f2a530-f496-464c-98fa-868c334b443d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
01pricedate
003/01/20001460.2001460.2002000-01-03
104/01/20001426.8001426.8002000-01-04
205/01/20001398.1251398.1252000-01-05
306/01/20001402.3751402.3752000-01-06
407/01/20001421.7501421.7502000-01-07
...............
553127/12/20214762.6754762.6752021-12-27
553228/12/20214792.2254792.2252021-12-28
553329/12/20214790.9754790.9752021-12-29
553430/12/20214789.2754789.2752021-12-30
553531/12/20214773.5004773.5002021-12-31
\n", + "

5536 rows × 4 columns

\n", + "
" + ], + "text/plain": [ + " 0 1 price date\n", + "0 03/01/2000 1460.200 1460.200 2000-01-03\n", + "1 04/01/2000 1426.800 1426.800 2000-01-04\n", + "2 05/01/2000 1398.125 1398.125 2000-01-05\n", + "3 06/01/2000 1402.375 1402.375 2000-01-06\n", + "4 07/01/2000 1421.750 1421.750 2000-01-07\n", + "... ... ... ... ...\n", + "5531 27/12/2021 4762.675 4762.675 2021-12-27\n", + "5532 28/12/2021 4792.225 4792.225 2021-12-28\n", + "5533 29/12/2021 4790.975 4790.975 2021-12-29\n", + "5534 30/12/2021 4789.275 4789.275 2021-12-30\n", + "5535 31/12/2021 4773.500 4773.500 2021-12-31\n", + "\n", + "[5536 rows x 4 columns]" + ] + }, + "execution_count": 113, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df['price'] = df[1]\n", + "df['date'] = pd.to_datetime(df[0], format = \"%d/%m/%Y\")\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "id": "a05a4c13-54ed-4304-ad37-541d0347257c", + "metadata": {}, + "outputs": [], + "source": [ + "dfsmall['price'] = dfsmall[0]\n", + "df['index']= np.arange(0,len(time_series),1)\n", + "dfsmall" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "id": "2d71eb4b-33e0-432e-99dc-2c132de38776", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "from tqdm import tqdm\n", + "\n", + "def compute_betti_curve(point_cloud, epsilons, dims):\n", + " \"\"\"Compute Betti numbers for a range of epsilon values for multiple dimensions.\"\"\"\n", + " return {dim: np.array([classical_betti_solver(point_cloud, epsilon, dim) \n", + " for epsilon in epsilons]) \n", + " for dim in dims}\n", + "\n", + "def normalize_betti_curves(betti_curves, dims):\n", + " \"\"\"Normalize Betti curves across all dimensions.\"\"\"\n", + " normalized_curves = []\n", + " \n", + " for curve in betti_curves:\n", + " # Find max value across all dimensions for this window\n", + " max_vals = {dim: np.max(curve[dim]) for dim in dims}\n", + " overall_max = max(max_vals.values())\n", + " \n", + " # Normalize each dimension by the overall max if it's non-zero\n", + " normalized = {}\n", + " for dim in dims:\n", + " if overall_max > 0:\n", + " normalized[dim] = curve[dim] / overall_max\n", + " else:\n", + " normalized[dim] = curve[dim]\n", + " normalized_curves.append(normalized)\n", + " \n", + " return normalized_curves\n", + "\n", + "def compute_lp_distances(df, window_size=7, p=2):\n", + " \"\"\"Compute Lp norm distances between successive windows of price data.\"\"\"\n", + " time_series = np.log(df['price']).to_numpy().squeeze()\n", + " \n", + " # Takens embedding parameters\n", + " N = 2 # embedding dimension\n", + " d = 1 # time delay\n", + " w = window_size\n", + " L = len(time_series)\n", + " dims = [0] # Now including dimension 2\n", + " \n", + " # Create range of epsilon values\n", + " epsilons = np.linspace(0, 0.05, 10)\n", + " \n", + " # Create point clouds using Takens embedding\n", + " vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + " K = L - (N-1)*d - w + 1 # number of windows\n", + " point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + " print(f\"N = {N}, w = {w}, L = {L}, K = {K}\")\n", + " \n", + " # Compute Betti curves for each window\n", + " betti_curves = []\n", + " for point_cloud in tqdm(point_clouds, desc=\"Computing Betti curves\"):\n", + " betti_curve = compute_betti_curve(point_cloud, epsilons, dims)\n", + " betti_curves.append(betti_curve)\n", + " \n", + " # Normalize Betti curves\n", + " normalized_curves = normalize_betti_curves(betti_curves, dims)\n", + " \n", + " # Compute Lp distances between successive normalized Betti curves\n", + " distances = {}\n", + " for dim in dims:\n", + " dim_distances = [np.power(np.sum(np.power(np.abs(b1[dim]), p)), 1/p) \n", + " for b1 in normalized_curves[:-1]]\n", + " \n", + " # Normalize distances within each dimension\n", + " dim_distances = np.array(dim_distances)\n", + " if np.max(dim_distances) > 0:\n", + " dim_distances = dim_distances / np.max(dim_distances)\n", + " \n", + " distances[dim] = pd.Series(dim_distances, \n", + " index=df.index[w+(N-1)*d:w+(N-1)*d+len(dim_distances)])\n", + " \n", + " # Add moving average smoothing\n", + " distances[f\"{dim}_ma\"] = distances[dim].rolling(window=5).mean()\n", + " \n", + " return distances, normalized_curves, epsilons\n", + "\n", + "def plot_lp_vs_price_and_betti(df, distances, betti_curves, epsilons, interval=100):\n", + " \"\"\"Plot price, Lp distances, and Betti curves at specified intervals.\"\"\"\n", + " fig = plt.figure(figsize=(20, 12))\n", + " gs = fig.add_gridspec(3, 1, height_ratios=[2, 2, 2])\n", + " \n", + " # Price plot\n", + " ax1 = fig.add_subplot(gs[0])\n", + " ax1.plot(df['date'].to_numpy(), df['price'].to_numpy(), 'b-', label='Price')\n", + " ax1.set_ylabel('Price')\n", + " ax1.legend()\n", + " \n", + " # Lp distances plot with moving averages\n", + " ax2 = fig.add_subplot(gs[1])\n", + " colors = ['r', 'b', 'g'] # Colors for dimensions 0, 1, 2\n", + " \n", + " # Plot raw distances in lighter colors\n", + " for dim, color in zip([0, 1, 2], colors):\n", + " ax2.plot(distances[dim].index.to_numpy(), distances[dim].to_numpy(), \n", + " f'{color}:', alpha=0.3, label=f'β₁ (raw)')\n", + " ax2.plot(distances[f'{dim}_ma'].index.to_numpy(), \n", + " distances[f'{dim}_ma'].to_numpy(), f'{color}-', \n", + " label=f'β{dim} (MA)')\n", + " \n", + " ax2.set_ylabel('Normalized Lp Distance')\n", + " ax2.legend()\n", + " \n", + " # Betti curves plot\n", + " ax3 = fig.add_subplot(gs[2])\n", + " linestyles = ['-', '--', ':'] # Different line styles for each dimension\n", + " colors = plt.cm.rainbow(np.linspace(0, 1, len(range(0, len(betti_curves), interval))))\n", + " \n", + " selected_indices = range(0, len(betti_curves), interval)\n", + " for color_idx, idx in enumerate(selected_indices):\n", + " color = colors[color_idx]\n", + " for dim, ls in zip([0, 1, 2], linestyles):\n", + " label = f't={idx}, β{dim}'\n", + " ax3.plot(epsilons, betti_curves[idx][dim], ls, color=color, label=label)\n", + " \n", + " ax3.set_xlabel('Epsilon')\n", + " ax3.set_ylabel('Normalized Betti Number')\n", + " ax3.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", + " \n", + " plt.tight_layout()\n", + " return fig" + ] + }, + { + "cell_type": "code", + "execution_count": 122, + "id": "6bf9ef38-8ae5-4851-b78b-3ace77ffd725", + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def compute_betti_curve(point_cloud, epsilons, dims):\n", + " \"\"\"Compute Betti numbers for a range of epsilon values for multiple dimensions.\"\"\"\n", + " return {dim: np.array([classical_betti_solver(point_cloud, epsilon, dim) \n", + " for epsilon in epsilons]) \n", + " for dim in dims}\n", + "\n", + "def normalize_betti_curves(betti_curves, dims):\n", + " \"\"\"Normalize Betti curves across all dimensions.\"\"\"\n", + " normalized_curves = []\n", + " \n", + " for curve in betti_curves:\n", + " # Find max value across all dimensions for this window\n", + " max_vals = {dim: np.max(curve[dim]) for dim in dims}\n", + " overall_max = max(max_vals.values())\n", + " \n", + " # Normalize each dimension by the overall max if it's non-zero\n", + " normalized = {}\n", + " for dim in dims:\n", + " if overall_max > 0:\n", + " normalized[dim] = curve[dim] / overall_max\n", + " else:\n", + " normalized[dim] = curve[dim]\n", + " normalized_curves.append(normalized)\n", + " \n", + " return normalized_curves\n", + "\n", + "def compute_lp_distances(df, window_size=7, p=2):\n", + " \"\"\"Compute Lp norm distances between successive windows of price data.\"\"\"\n", + " time_series = np.log(df['price']).to_numpy().squeeze()\n", + " \n", + " # Takens embedding parameters\n", + " N = 2 # embedding dimension\n", + " d = 1 # time delay\n", + " w = window_size\n", + " L = len(time_series)\n", + " dims = [0,1] # Now including dimension 2\n", + " \n", + " # Create range of epsilon values\n", + " epsilons = np.linspace(0, 0.05, 10)\n", + " \n", + " # Create point clouds using Takens embedding\n", + " vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + " K = L - (N-1)*d - w + 1 # number of windows\n", + " point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + " print(f\"N = {N}, w = {w}, L = {L}, K = {K}\")\n", + " \n", + " # Compute Betti curves for each window\n", + " betti_curves = []\n", + " for point_cloud in tqdm(point_clouds, desc=\"Computing Betti curves\"):\n", + " betti_curve = compute_betti_curve(point_cloud, epsilons, dims)\n", + " betti_curves.append(betti_curve)\n", + " \n", + " # Normalize Betti curves\n", + " normalized_curves = normalize_betti_curves(betti_curves, dims)\n", + " \n", + " # Compute Lp distances between successive normalized Betti curves\n", + " distances = {}\n", + " for dim in dims:\n", + " dim_distances = [np.power(np.sum(np.power(np.abs(b1[dim]), p)), 1/p) \n", + " for b1 in normalized_curves[:-1]]\n", + " \n", + " # Normalize distances within each dimension\n", + " dim_distances = np.array(dim_distances)\n", + " if np.max(dim_distances) > 0:\n", + " dim_distances = dim_distances / np.max(dim_distances)\n", + " \n", + " distances[dim] = pd.Series(dim_distances, \n", + " index=df.index[w+(N-1)*d:w+(N-1)*d+len(dim_distances)])\n", + " \n", + " # Add moving average smoothing\n", + " distances[f\"{dim}_ma\"] = distances[dim].rolling(window=5).mean()\n", + " \n", + " return distances, normalized_curves, epsilons\n", + "\n", + "def plot_lp_vs_price_and_betti(df, distances, betti_curves, epsilons, interval=100):\n", + " \"\"\"Plot price, Lp distances, and Betti curves at specified intervals.\"\"\"\n", + " fig = plt.figure(figsize=(20, 12))\n", + " gs = fig.add_gridspec(3, 1, height_ratios=[2, 2, 2])\n", + " \n", + " # Price plot\n", + " ax1 = fig.add_subplot(gs[0])\n", + " ax1.plot(df['date'].to_numpy(), df['price'].to_numpy(), 'b-', label='Price')\n", + " ax1.set_ylabel('Price')\n", + " ax1.legend()\n", + " \n", + " # Lp distances plot with moving averages\n", + " ax2 = fig.add_subplot(gs[1])\n", + " colors = ['r', 'b', 'g'] # Colors for dimensions 0, 1, 2\n", + " \n", + " # Plot raw distances in lighter colors\n", + " for dim, color in zip([0, 1, 2], colors):\n", + " ax2.plot(distances[dim].index.to_numpy(), distances[dim].to_numpy(), \n", + " f'{color}:', alpha=0.3, label=f'β₁ (raw)')\n", + " ax2.plot(distances[f'{dim}_ma'].index.to_numpy(), \n", + " distances[f'{dim}_ma'].to_numpy(), f'{color}-', \n", + " label=f'β{dim} (MA)')\n", + " \n", + " ax2.set_ylabel('Normalized Lp Distance')\n", + " ax2.legend()\n", + " \n", + " # Betti curves plot\n", + " ax3 = fig.add_subplot(gs[2])\n", + " linestyles = ['-', '--', ':'] # Different line styles for each dimension\n", + " colors = plt.cm.rainbow(np.linspace(0, 1, len(range(0, len(betti_curves), interval))))\n", + " \n", + " selected_indices = range(0, len(betti_curves), interval)\n", + " for color_idx, idx in enumerate(selected_indices):\n", + " color = colors[color_idx]\n", + " for dim, ls in zip([0, 1, 2], linestyles):\n", + " label = f't={idx}, β{dim}'\n", + " ax3.plot(epsilons, betti_curves[idx][dim], ls, color=color, label=label)\n", + " \n", + " ax3.set_xlabel('Epsilon')\n", + " ax3.set_ylabel('Normalized Betti Number')\n", + " ax3.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", + " \n", + " plt.tight_layout()\n", + " return fig" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c19f3c1-dade-4717-ba5e-f28a1b186b18", + "metadata": {}, + "outputs": [], + "source": [ + "df1 = df[1900:2400]\n", + "# Compute distances and get Betti curves\n", + "distances, betti_curves, epsilons = compute_lp_distances(df)\n", + "# Plot everything" + ] + }, + { + "cell_type": "code", + "execution_count": 124, + "id": "6ef7b180-6640-40c1-8c47-5041be3156b9", + "metadata": {}, + "outputs": [], + "source": [ + "def plot_lp_vs_price_and_betti_classic(df, distances, betti_curves, epsilons, interval=100):\n", + " \"\"\"Plot price, Lp distances, and Betti curves at specified intervals.\"\"\"\n", + " fig = plt.figure(figsize=(20, 12))\n", + " gs = fig.add_gridspec(3, 1, height_ratios=[2, 2, 2])\n", + " \n", + " # Price plot\n", + " ax1 = fig.add_subplot(gs[0])\n", + " ax1.plot(df['index'].to_numpy(), df['price'].to_numpy(), 'b-', label='Price')\n", + " ax1.set_ylabel('Price')\n", + " ax1.legend()\n", + " \n", + " # Lp distances plot with moving averages\n", + " ax2 = fig.add_subplot(gs[1])\n", + " colors = ['r', 'b', 'g'] # Colors for dimensions 0, 1, 2\n", + " \n", + " # Plot raw distances in lighter colors\n", + " for dim, color in zip([0, 1, 2], colors):\n", + " if dim in distances and f'{dim}_ma' in distances:\n", + " ax2.plot(range(len(distances[dim])), distances[dim], \n", + " f'{color}:', alpha=0.3, label=f'β{dim} (raw)')\n", + " ax2.plot(range(len(distances[f'{dim}_ma'])), \n", + " distances[f'{dim}_ma'], f'{color}-', \n", + " label=f'β{dim} (MA)')\n", + " else:\n", + " print(f\"Key {dim} or {dim}_ma not found in distances dictionary\")\n", + "\n", + " \n", + " ax2.set_ylabel('Normalized Lp Distance')\n", + " ax2.legend()\n", + " \n", + " # Betti curves plot\n", + " ax3 = fig.add_subplot(gs[2])\n", + " linestyles = ['-', '--', ':'] # Different line styles for each dimension\n", + " colors = plt.cm.rainbow(np.linspace(0, 1, len(range(0, len(betti_curves), interval))))\n", + " \n", + " selected_indices = range(0, len(betti_curves), interval)\n", + " for color_idx, idx in enumerate(selected_indices):\n", + " color = colors[color_idx]\n", + " for dim, ls in zip([0, 1, 2], linestyles):\n", + " label = f't={idx}, β{dim}'\n", + " ax3.plot(epsilons, betti_curves[idx][dim], ls, color=color, label=label)\n", + " \n", + " ax3.set_xlabel('Epsilon')\n", + " ax3.set_ylabel('Normalized Betti Number')\n", + " ax3.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", + " \n", + " plt.tight_layout()\n", + " return fig" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "de37efb2-26b5-4d99-b60d-b804aa7c3532", + "metadata": {}, + "outputs": [], + "source": [ + "plot_lp_vs_price_and_betti_classic(df, distances, betti_curves, epsilons, interval=100)\n", + "plt.savefig('betti_analysis_full_norm.svg', format='svg', dpi=300)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "id": "2ef7bcf9-5033-4e3b-b934-29bdf42ba359", + "metadata": {}, + "outputs": [], + "source": [ + "def compute_betti_curve(point_cloud, epsilons, dims):\n", + " \"\"\"Compute Betti numbers for a range of epsilon values for multiple dimensions.\"\"\"\n", + " return {dim: np.array([classical_betti_solver(point_cloud, epsilon, dim) \n", + " for epsilon in epsilons]) \n", + " for dim in dims}\n", + "\n", + "def normalize_betti_curves(betti_curves, dims):\n", + " \"\"\"Normalize Betti curves across all dimensions.\"\"\"\n", + " normalized_curves = []\n", + " \n", + " for curve in betti_curves:\n", + " # Find max value across all dimensions for this window\n", + " max_vals = {dim: np.max(curve[dim]) for dim in dims}\n", + " overall_max = max(max_vals.values())\n", + " \n", + " # Normalize each dimension by the overall max if it's non-zero\n", + " normalized = {}\n", + " for dim in dims:\n", + " if overall_max > 0:\n", + " normalized[dim] = curve[dim] / overall_max\n", + " else:\n", + " normalized[dim] = curve[dim]\n", + " normalized_curves.append(normalized)\n", + " \n", + " return normalized_curves\n", + "\n", + "def compute_lp_distances(df, window_size=7, p=2):\n", + " \"\"\"Compute Lp norm distances between successive windows of price data.\"\"\"\n", + " time_series = np.log(df['price']).to_numpy().squeeze()\n", + " \n", + " # Takens embedding parameters\n", + " N = 10 # embedding dimension\n", + " d = 2 # time delay\n", + " w = window_size\n", + " L = len(time_series)\n", + " dims = [0, 1, 2] # Now including dimension 2\n", + " \n", + " # Create range of epsilon values\n", + " epsilons = np.linspace(0, 0.1, 40)\n", + " \n", + " # Create point clouds using Takens embedding\n", + " vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + " K = L - (N-1)*d - w + 1 # number of windows\n", + " point_clouds = np.array([vectors[i:i+w] for i in range(K)])\n", + " print(f\"N = {N}, w = {w}, L = {L}, K = {K}\")\n", + " \n", + " # Compute Betti curves for each window\n", + " betti_curves = []\n", + " for point_cloud in tqdm(point_clouds, desc=\"Computing Betti curves\"):\n", + " betti_curve = compute_betti_curve(point_cloud, epsilons, dims)\n", + " betti_curves.append(betti_curve)\n", + " \n", + " # Normalize Betti curves\n", + " normalized_curves = normalize_betti_curves(betti_curves, dims)\n", + " \n", + " # Compute Lp distances between successive normalized Betti curves\n", + " distances = {}\n", + " for dim in dims:\n", + " dim_distances = [np.power(np.sum(np.power(np.abs(b1[dim]), p)), 1/p) \n", + " for b1 in normalized_curves[:-1]]\n", + " \n", + " # Normalize distances within each dimension\n", + " dim_distances = np.array(dim_distances)\n", + " if np.max(dim_distances) > 0:\n", + " dim_distances = dim_distances / np.max(dim_distances)\n", + " \n", + " distances[dim] = pd.Series(dim_distances, \n", + " index=df.index[w+(N-1)*d:w+(N-1)*d+len(dim_distances)])\n", + " \n", + " # Add moving average smoothing\n", + " distances[f\"{dim}_ma\"] = distances[dim].rolling(window=5).mean()\n", + " \n", + " return distances, normalized_curves, epsilons\n", + "\n", + "def plot_lp_vs_price_and_betti(df, distances, betti_curves, epsilons, interval=100):\n", + " \"\"\"Plot price, Lp distances, and Betti curves at specified intervals.\"\"\"\n", + " fig = plt.figure(figsize=(20, 12))\n", + " gs = fig.add_gridspec(3, 1, height_ratios=[2, 2, 2])\n", + " \n", + " # Price plot\n", + " ax1 = fig.add_subplot(gs[0])\n", + " ax1.plot(df['date'].to_numpy(), df['price'].to_numpy(), 'b-', label='Price')\n", + " ax1.set_ylabel('Price')\n", + " ax1.legend()\n", + " \n", + " # Lp distances plot with moving averages\n", + " ax2 = fig.add_subplot(gs[1])\n", + " colors = ['r', 'b', 'g'] # Colors for dimensions 0, 1, 2\n", + " \n", + " # Plot raw distances in lighter colors\n", + " for dim, color in zip([0, 1, 2], colors):\n", + " ax2.plot(distances[dim].index.to_numpy(), distances[dim].to_numpy(), \n", + " f'{color}:', alpha=0.3, label=f'β₁ (raw)')\n", + " ax2.plot(distances[f'{dim}_ma'].index.to_numpy(), \n", + " distances[f'{dim}_ma'].to_numpy(), f'{color}-', \n", + " label=f'β{dim} (MA)')\n", + " \n", + " ax2.set_ylabel('Normalized Lp Distance')\n", + " ax2.legend()\n", + " \n", + " # Betti curves plot\n", + " ax3 = fig.add_subplot(gs[2])\n", + " linestyles = ['-', '--', ':'] # Different line styles for each dimension\n", + " colors = plt.cm.rainbow(np.linspace(0, 1, len(range(0, len(betti_curves), interval))))\n", + " \n", + " selected_indices = range(0, len(betti_curves), interval)\n", + " for color_idx, idx in enumerate(selected_indices):\n", + " color = colors[color_idx]\n", + " for dim, ls in zip([0, 1, 2], linestyles):\n", + " label = f't={idx}, β{dim}'\n", + " ax3.plot(epsilons, betti_curves[idx][dim], ls, color=color, label=label)\n", + " \n", + " ax3.set_xlabel('Epsilon')\n", + " ax3.set_ylabel('Normalized Betti Number')\n", + " ax3.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", + " \n", + " plt.tight_layout()\n", + " return fig" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b9d53592-f82d-433d-b403-1e16b4131df4", + "metadata": {}, + "outputs": [], + "source": [ + "df_filtered = df[(df['date'] >= '2007-01-01') & (df['date'] <= '2010-12-31')]\n", + "distances, betti_curves, epsilons = compute_lp_distances(df_filtered)\n", + "# Plot everything" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77c87119-cb70-4001-b275-38e7eb19c1ad", + "metadata": {}, + "outputs": [], + "source": [ + "distances_quantum=distances;\n", + "betti_curves_quantum=betti_curves;\n", + "epsilons_quantum=epsilons;" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93cc4e93-06ac-4823-b1d7-d62507dd98b5", + "metadata": {}, + "outputs": [], + "source": [ + "plot_lp_vs_price_and_betti(df_filtered, distances_quantum, betti_curves_quantum, epsilons_quantum, interval=100)\n", + "#print(distances_quantum[0].to_numpy())\n", + "plt.savefig(f'betti_analysis_norm_2008_{7}.svg', format='svg', dpi=300)\n", + "# plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ae1faa8-d47b-45e5-afba-e338fec445b7", + "metadata": {}, + "outputs": [], + "source": [ + "def plot_betti_heatmaps(df, normalized_curves, epsilons, dims):\n", + " \"\"\"\n", + " Plot heat maps for each Betti curve βₖ as a function of date and epsilon.\n", + " \n", + " Parameters:\n", + " df : pandas.DataFrame\n", + " The dataframe containing the 'date' column.\n", + " normalized_curves : list of dicts\n", + " Each element is a dictionary with keys corresponding to dimensions (k) \n", + " and values being arrays (len(epsilons),) of normalized Betti numbers.\n", + " epsilons : array-like\n", + " The range of epsilon values.\n", + " dims : list\n", + " List of dimensions (e.g. [0, 1]) to plot.\n", + " \n", + " Returns:\n", + " fig : matplotlib.figure.Figure\n", + " The resulting figure with subplots.\n", + " \"\"\"\n", + " num_dims = len(dims)\n", + " fig, axs = plt.subplots(1, num_dims, figsize=(5 * num_dims, 4), squeeze=False)\n", + " \n", + " # Extract dates from the dataframe\n", + " dates = df['date'].iloc[len(df) - len(normalized_curves):]\n", + " \n", + " for i, dim in enumerate(dims):\n", + " # Build a matrix with shape (n_time, n_epsilon) for dimension k.\n", + " matrix = np.array([nc[dim] for nc in normalized_curves])\n", + " \n", + " # Plot using imshow\n", + " im = axs[0, i].imshow(matrix.T, aspect='auto', origin='lower',\n", + " extent=[0, len(dates) - 1, epsilons[0], epsilons[-1]])\n", + " axs[0, i].set_title(f\"Heatmap of β{dim}\")\n", + " axs[0, i].set_xlabel(\"Date\")\n", + " axs[0, i].set_ylabel(\"Epsilon\")\n", + " \n", + " # Set x-axis ticks and labels\n", + " num_ticks = 10 # Increased number of ticks\n", + " tick_locations = np.linspace(0, len(dates) - 1, num_ticks).astype(int)\n", + " axs[0, i].set_xticks(tick_locations)\n", + " \n", + " # Format dates to show only month (as number) and year\n", + " formatted_dates = [f\"{date.month:02d}/{date.year}\" for date in dates.iloc[tick_locations]]\n", + " axs[0, i].set_xticklabels(formatted_dates, rotation=45, ha='right')\n", + " \n", + " fig.colorbar(im, ax=axs[0, i], orientation='vertical')\n", + " \n", + " plt.tight_layout()\n", + " return fig\n", + "\n", + "normalized_curves = normalize_betti_curves(betti_curves_quantum,[0,1,2])\n", + "plot_betti_heatmaps(df_filtered,normalized_curves,epsilons_quantum,[1])\n", + "plt.savefig(f'betti1_analysis_heatmap_2000_{5}.svg', format='svg', dpi=300)" + ] + }, + { + "cell_type": "markdown", + "id": "d1c2e4b5", + "metadata": {}, + "source": [ + "## *BONUS:* Explore future directions of quantum TDA\n", + "\n", + "The following is a non-exhaustive list of possible next steps for the quantum TDA pipeline. It is recommended to at least explore 1 option or sub-option.\n", + "\n", + "- **Find more of applications of TDA in finance**:\n", + "\n", + " There are several directions where to extend the analysis. Most work on time series analysis has used persistent homology, and more specifically, the $L^{P}$ norm of persistence landscapes, which can be used to detect early warning signals of imminent market crashes. This is precisely studied in the seminal work by Gidea and Katz, see [ref](https://arxiv.org/abs/1703.04385)\n", + " - Analyze financial correlation network and their degree of association with Betti curves or other topological features. From the time-series of multiple stock prices, we can build time-dependent correlation networks, which exhibit topological structures and might show some association to the evolution of betti curves or other topological data measures. Generally speaking, the cross correlations in a stock market will be in the form of a high-dimension topological space, with more complicated features. One can also think about other time varying financial graphs (e.g. cryptocurrencies). The following articles can help uncover more applications: \n", + " \n", + " - [Integral Betti signature confirms the hyperbolic geometry of brain, climate,and financial networks](https://www.arxiv.org/pdf/2406.15505)\n", + " - [Using Topological Data Analysis (TDA) and Persistent Homology to Analyze the Stock Markets in Singapore and Taiwan](https://www.frontiersin.org/journals/physics/articles/10.3389/fphy.2021.572216/full)\n", + " - Build a ML classifier or regressor on top of vectorized features such as Betti Curves (given their potential to identify trends, patterns or potential turning points in the market) to help with investment or risk management strategies. Show that Betti curves have some predictive skill, as key topological descriptors. See [ref1](https://arxiv.org/abs/2411.13881) and [ref2](https://www.sciencedirect.com/science/article/pii/S2405918823000235) for further information on the topic.\n", + "- **A hybrid and more NISQ-friendly quantum TDA pipeline**:\n", + " \n", + " QPE remains primarily theoretical. Its circuits are simply too deep to run on real hardware. Come up an with iterative or hybrid quantum phase estimation protocol or use tools that increase the algorithmic performance when running quantum circuits on real hardware. Benchmark them against textbook-QPE circuits. Here are some proposals to subtitute the QPE part:\n", + " - Variational Quantum Deflation (VQD) Algorithm: VQD is a quantum algorithm that uses a variational technique to find the k eigenvalues of the Hamiltonian H of a given system. [ref](https://quantum-journal.org/papers/q-2019-07-01-156/)\n", + " - Variational Quantum Eigensolver (VQE): Using VQE to determine the spectra of adjancency or laplacian matrix. Inspired by: [ref](https://arxiv.org/pdf/1912.12366)\n", + " \n", + " Finally, run some circuits on simulator + real hardware and compare the performance (runtime, noise effects, # resources) of the new proposal to the QPE solution of the above sections.\n", + "\n", + "- **A proper procedure of encoding the Laplacian matrix to the unitary**:\n", + "\n", + " In Step 3, encoding the exponential matrix is recommanded. An alternative approach is to conduct the Paulis decomposition on the Laplacian, then followed by Trotterization. Can you implement this approach in your pipeline? What parameters influence the accuracy? Can you optimize your code to minimize the circuit depth?\n", + "\n", + "- **Extend the quantum TDA to extract persistent Betti numbers**: \n", + " \n", + " Implement a quantum TDA algorithm for persistent Betti numbers. Esstimating the persistent Betti numbers is a more general task than estimating the Betti number and it is more practical for TDA. It is an open problem to construct a quantum algorithm for the persistent Betti numbers in a way that is preferable for NISQ devices, and the only current implementation of a quantum algorithm for persistent betti number is shown [here](https://quantum-journal.org/papers/q-2022-12-07-873/pdf/)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "884527bc-bce6-4560-88d5-f0eb2119455e", + "metadata": {}, + "outputs": [], + "source": [ + "N = 3 # embedding dimension\n", + "d = 1 # time delay\n", + "w = 10 # window size\n", + "\n", + "L = len(time_series)\n", + "vectors = np.array([time_series[i:L-(N-1)*d+i] for i in range(0, N*d, d)]).T\n", + "\n", + "K = L - (N-1)*d - w + 1 # number of windows\n", + "Z = np.array([vectors[i:i+w] for i in range(K)])\n", + "print(f\"N = {N}, w = {w}, L = {L}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "acfaa739-9e12-4290-b098-c1020ed5f847", + "metadata": {}, + "outputs": [], + "source": [ + "import gudhi\n", + "\n", + "epsilon = 0.2 # maximum edge length\n", + "max_dim = 2 # maximum simplex dimension\n", + "\n", + "all_simplices = []\n", + "\n", + "point_cloud = Z[0]\n", + "\n", + "# Simplicial Complex\n", + "rips = gudhi.RipsComplex(points=point_cloud, max_edge_length=epsilon)\n", + "filtration = rips.create_simplex_tree(max_dimension=max_dim).get_filtration()\n", + "\n", + "# Extract simplices by dimension\n", + "simplex_tree = [[] for _ in range(max_dim + 1)]\n", + "for simplex, filtration_value in filtration:\n", + " if filtration_value <= epsilon:\n", + " dim = len(simplex) - 1\n", + " simplex_tree[dim].append(simplex)\n", + "\n", + "print(f\"num 0-simplices: {len(simplex_tree[0])}\")\n", + "print(f\"num 1-simplices: {len(simplex_tree[1])}\")\n", + "print(f\"num 2-simplices: {len(simplex_tree[2])}\")\n", + "for dim, simplices in enumerate(simplex_tree):\n", + " print(f\"{dim}-simplices: {simplices}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "01b1899d-b92b-4e69-9fd4-8167f2b5fc2b", + "metadata": {}, + "outputs": [], + "source": [ + "boundary1 = boundary(1, simplex_tree)\n", + "boundary2 = boundary(2, simplex_tree)\n", + "\n", + "print(\"Boundary 1:\", boundary1.shape)\n", + "print(boundary1)\n", + "\n", + "print(\"Boundary 2:\", boundary2.shape)\n", + "print(boundary2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ebd6e21e-12f6-4172-abd8-c94b711ad640", + "metadata": {}, + "outputs": [], + "source": [ + "k = 1\n", + "laplacian = get_laplacian(k, simplex_tree)\n", + "\n", + "U = get_unitary(laplacian)\n", + "\n", + "print(\"Laplacian:\", laplacian.shape)\n", + "print(laplacian)\n", + "print(\"Unitary:\", U.shape)\n", + "print(U)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ac491552-88af-42ac-b067-fb45d34b1ab4", + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit.synthesis import SuzukiTrotter\n", + "from qiskit.circuit.library import PauliEvolutionGate\n", + "from qiskit.circuit import Parameter\n", + "from qiskit.quantum_info import Operator, SparsePauliOp\n", + "\n", + "pauli_op = SparsePauliOp.from_operator(laplacian)\n", + "evolution_time = 1.19\n", + "trotter_steps = 44\n", + "\n", + "# Create a Trotterized unitary evolution\n", + "trotter_op = PauliEvolutionGate(\n", + " pauli_op, \n", + " time=evolution_time, \n", + " synthesis=SuzukiTrotter(reps=trotter_steps)\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8c2ee193-72b5-43cd-a0ad-515b93396cd4", + "metadata": {}, + "outputs": [], + "source": [ + "# Create a quantum circuit\n", + "from qiskit import QuantumCircuit\n", + "num_qubits = pauli_op.num_qubits\n", + "qc = QuantumCircuit(num_qubits)\n", + "\n", + "# Apply the Trotterized operator\n", + "qc.append(trotter_op, range(num_qubits))\n", + "qc.draw()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1e3aecf4-45c7-424d-b91e-d3ba48b46823", + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.linalg import expm, eigvals\n", + "exact_unitary = expm(-1j * laplacian * evolution_time)\n", + "\n", + "# Compute eigenvalues of the exact unitary\n", + "exact_eigenvalues = eigvals(exact_unitary)\n", + "\n", + "trotterized_unitary = Operator(qc).data\n", + "trotterized_eigenvalues = eigvals(trotterized_unitary)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d3a1113a-22b8-43f8-9872-024a8f6620cb", + "metadata": {}, + "outputs": [], + "source": [ + "# Sort eigenvalues to ensure they're compared correctly\n", + "exact_eigenvalues_sorted = np.sort(exact_eigenvalues)\n", + "trotterized_eigenvalues_sorted = np.sort(trotterized_eigenvalues)\n", + "\n", + "# Calculate relative error\n", + "relative_error = np.abs(exact_eigenvalues_sorted - trotterized_eigenvalues_sorted) / np.abs(exact_eigenvalues_sorted)\n", + "\n", + "# Print maximum and average relative error\n", + "print(f\"Maximum relative error: {np.max(relative_error)}\")\n", + "print(f\"Average relative error: {np.mean(relative_error)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fb5186dd-146b-4e4f-a3ab-13cbcbd4db5d", + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure(figsize=(10, 6))\n", + "plt.scatter(np.real(exact_eigenvalues), np.imag(exact_eigenvalues), label='Exact', alpha=0.7)\n", + "plt.scatter(np.real(trotterized_eigenvalues), np.imag(trotterized_eigenvalues), label='Trotterized', alpha=0.7, marker='x')\n", + "\n", + "plt.xlabel('Real part')\n", + "plt.ylabel('Imaginary part')\n", + "plt.title('Comparison of Eigenvalues')\n", + "plt.legend()\n", + "plt.grid(True)\n", + "plt.savefig('trotter.svg', format='svg', dpi=300)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a5b831f-74bc-41fe-a523-2e6eb54bcecd", + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.linalg import sqrtm\n", + "\n", + "def trace_distance(A, B):\n", + " return 0.5 * np.trace(sqrtm((A - B).conj().T @ (A - B)))\n", + "\n", + "error = trace_distance(exact_unitary, trotterized_unitary)\n", + "print(f\"Trace distance between matrices: {error}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "28beaf99-d3d9-4ca7-b58e-faa4738679bd", + "metadata": {}, + "outputs": [], + "source": [ + "# If you still need the SparsePauliOp representation\n", + "trotterized_op = SparsePauliOp.from_operator(trotterized_unitary)\n", + "coefficients = trotterized_op.coeffs\n", + "pauli_matrices = trotterized_op.paulis\n", + "\n", + "# Step 3: Reconstruct the matrix using the formula\n", + "def reconstruct_matrix(coefficients, pauli_matrices):\n", + " result = np.eye(2**len(pauli_matrices[0])) # Identity matrix of appropriate size\n", + " for theta, sigma in zip(coefficients, pauli_matrices):\n", + " pauli_matrix = SparsePauliOp(sigma).to_matrix()\n", + " result = result @ (np.cos(theta) * np.eye(2**len(sigma)) + 1j * np.sin(theta) * pauli_matrix)\n", + " return result\n", + "\n", + "reconstructed_matrix = reconstruct_matrix(coefficients, pauli_matrices)\n", + "\n", + "# Step 4: Compare the reconstructed matrix to the original unitary\n", + "error_frobenius = np.linalg.norm(exact_unitary - reconstructed_matrix, 'fro')\n", + "error_trace = np.trace(np.abs(exact_unitary - reconstructed_matrix))\n", + "\n", + "print(f\"Frobenius norm of the difference: {error_frobenius}\")\n", + "print(f\"Trace distance: {error_trace}\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c47d6b40-023b-4344-8bbb-3227aa5b7d4a", + "metadata": {}, + "outputs": [], + "source": [ + "fig, axs = plt.subplots(2, 2, figsize=(12, 12))\n", + "\n", + "axs[0, 0].imshow(np.real(exact_unitary))\n", + "axs[0, 0].set_title(\"Real part of original unitary\")\n", + "\n", + "axs[0, 1].imshow(np.imag(exact_unitary))\n", + "axs[0, 1].set_title(\"Imaginary part of original unitary\")\n", + "\n", + "axs[1, 0].imshow(np.real(reconstructed_matrix))\n", + "axs[1, 0].set_title(\"Real part of reconstructed matrix\")\n", + "\n", + "axs[1, 1].imshow(np.imag(reconstructed_matrix))\n", + "axs[1, 1].set_title(\"Imaginary part of reconstructed matrix\")\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + "\n", + "# Plot the difference\n", + "plt.figure(figsize=(10, 4))\n", + "\n", + "plt.subplot(121)\n", + "plt.imshow(np.abs(np.real(exact_unitary - reconstructed_matrix)))\n", + "plt.colorbar()\n", + "plt.title(\"Absolute difference (Real part)\")\n", + "\n", + "plt.subplot(122)\n", + "plt.imshow(np.abs(np.imag(exact_unitary - reconstructed_matrix)))\n", + "plt.colorbar()\n", + "plt.title(\"Absolute difference (Imaginary part)\")\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "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.12.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}