{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from itertools import product\n",
    "from collections import defaultdict\n",
    "\n",
    "from pyqcs import CZ, GenericGate, State, H\n",
    "from pyqcs.graph.util import C_L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.5000000000000001+0j)*|0b0> + (0.5000000000000001+0j)*|0b1> + (0.5000000000000001+0j)*|0b10> + (0.5000000000000001+0j)*|0b11>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plus_state_state_2 = (H(0) | H(1)) * State.new_zero_state(2)\n",
    "plus_state_state_2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(0.5000000000000001+0j)*|0b0> + (0.5000000000000001+0j)*|0b1> + (0.5000000000000001+0j)*|0b10> + (-0.5000000000000001-0j)*|0b11>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "plus_state_state_2_cz = CZ(0, 1) * plus_state_state_2\n",
    "plus_state_state_2_cz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "circuits = [GenericGate(0, C_L[c0]) | GenericGate(1, C_L[c1]) for c0,c1 in product(range(24), range(24))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "resulting_states = [c * s for c,s in product(circuits, (plus_state_state_2, plus_state_state_2_cz))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_equivalent_states(s, resulting_states):\n",
    "    for i,test in enumerate(resulting_states):\n",
    "        if(test == s):\n",
    "            yield i\n",
    "            \n",
    "equivalent_states = [list(get_equivalent_states(s, resulting_states)) for s in resulting_states]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "equivalent_state_counts = [len(e) - 1 for e in equivalent_states]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 4644 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.bar(range(len(resulting_states)), equivalent_state_counts)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "clusters = set((tuple(sorted(v)) for v in equivalent_states))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{15, 23}"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "set(equivalent_state_counts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1152"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "len(equivalent_states)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 4644 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "resulting_states_after_cz = [CZ(0, 1) * s for s in resulting_states]\n",
    "equivalent_states_after_cz = [list(get_equivalent_states(s, resulting_states_after_cz)) for s in resulting_states_after_cz]\n",
    "equivalent_state_counts_after_cz = [len(e) - 1 for e in equivalent_states_after_cz]\n",
    "\n",
    "plt.bar(range(len(resulting_states)), equivalent_state_counts_after_cz)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{15, 23}"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clusters_after_cz = set((tuple(sorted(v)) for v in equivalent_states))\n",
    "set(equivalent_state_counts_after_cz)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clusters == clusters_after_cz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "resulting_states_after_cz_C_L = [c*s for c,s in product(circuits, resulting_states)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "equivalent_states_after_cz_C_L = [list(get_equivalent_states(s, resulting_states_after_cz_C_L)) for s in resulting_states_after_cz_C_L]\n",
    "equivalent_state_counts_after_cz_C_L = [len(e) - 1 for e in equivalent_states_after_cz_C_L]\n",
    "\n",
    "plt.bar(range(len(resulting_states_after_cz_C_L)), equivalent_state_counts_after_cz_C_L)\n",
    "plt.show()"
   ]
  }
 ],
 "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
}
