{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "simulating... 99 %  \n",
      "done.\n"
     ]
    },
    {
     "data": {
      "image/png": "[encoded data, 38708 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from pyqcs import State, sample\n",
    "from transfer_matrix import T_time_slice\n",
    "from hamiltonian import H\n",
    "\n",
    "from scipy.linalg import expm\n",
    "\n",
    "nqbits = 3\n",
    "g = 0.20\n",
    "N = 50\n",
    "t_stop = 5\n",
    "delta_t = 0.05\n",
    "qbits = list(range(nqbits))\n",
    "\n",
    "n_sample = 400\n",
    "measure = 0b10\n",
    "\n",
    "\n",
    "results_qc = []\n",
    "results_np = []\n",
    "print()\n",
    "for t in np.arange(0, t_stop, delta_t):\n",
    "    # QC simulation\n",
    "    state = State.new_zero_state(nqbits)\n",
    "\n",
    "    for _ in range(N):\n",
    "        state = T_time_slice(qbits, t, g, N) * state\n",
    "\n",
    "    #result = sample(state, measure, n_sample)\n",
    "\n",
    "    #results_qc.append(result[0] / n_sample)\n",
    "\n",
    "    amplitude = np.sqrt(np.sum(np.abs(state._qm_state[[False if (i & measure) else True for i in range(2**nqbits)]])**2))\n",
    "    results_qc.append(amplitude)\n",
    "\n",
    "    # Simulation using matrices\n",
    "    np_zero_state = np.zeros(2**nqbits)\n",
    "    np_zero_state[0] = 1\n",
    "\n",
    "    itH = np.matrix(-1j * t * H(nqbits, g))\n",
    "    T = expm(itH)\n",
    "\n",
    "    np_state = T.dot(np_zero_state)\n",
    "    amplitude = np.sqrt(np.sum(np.abs(np_state[[False if (i & measure) else True for i in range(2**nqbits)]])**2))\n",
    "    results_np.append(amplitude)\n",
    "\n",
    "    print(f\"simulating... {int(t/t_stop*100)} %  \", end=\"\\r\")\n",
    "print()\n",
    "print(\"done.\")\n",
    "\n",
    "errors_trotter = np.arange(0, t_stop, delta_t)**2 / N**2\n",
    "\n",
    "\n",
    "h0 = plt.errorbar(np.arange(0, t_stop, delta_t), results_qc, yerr=errors_trotter, label=f\"Quantum computing ({n_sample} samples, {N} trotterization steps)\")\n",
    "h1, = plt.plot(np.arange(0, t_stop, delta_t), results_np, label=\"Classical simulation using explicit transfer matrix\")\n",
    "plt.xlabel(\"t\")\n",
    "plt.ylabel(r\"$|0\\rangle$ probability amplitude for second spin\")\n",
    "plt.title(f\"{nqbits} site spin chain with g={g} coupling to external field\")\n",
    "plt.legend(handles=[h0, h1])\n",
    "\n",
    "plt.show()\n",
    "\n"
   ]
  }
 ],
 "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.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
