diff --git a/demos/AllFeatures.ipynb b/demos/AllFeatures.ipynb index 21683853..5c61e916 100644 --- a/demos/AllFeatures.ipynb +++ b/demos/AllFeatures.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -85,7 +85,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -112,247 +112,247 @@ " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", + " \r\n", " \r\n", " \r\n", " \r\n", @@ -955,7 +955,7 @@ "
" ] }, - "execution_count": 6, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -973,7 +973,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -1000,627 +1000,627 @@ " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", + " \r\n", " \r\n", " \r\n", " \r\n", @@ -3293,7 +3293,7 @@ "
" ] }, - "execution_count": 7, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -3311,13 +3311,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -3577,7 +3577,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -3605,7 +3605,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -3635,7 +3635,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -3670,7 +3670,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -3703,7 +3703,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -3750,13 +3750,13 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -4019,7 +4019,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -4045,7 +4045,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -4054,7 +4054,7 @@ "([10, 12], [9, 11])" ] }, - "execution_count": 20, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -4071,13 +4071,14 @@ "\n", "This can be done either manually:\n", "\n", - " ``g.inputs = list_of_inputs; g.outputs = list_of_outputs``\n", - "Or by PyZX trough calling ``g.auto_detect_inputs()``. This function makes all the vertices on the leftmost row inputs, and the vertices on the rightmost row outputs. For example:" + " g.inputs = list_of_inputs; g.outputs = list_of_outputs\n", + " \n", + "or by PyZX trough calling ``g.auto_detect_inputs()``. This function makes all boundaries pointing to the right inputs, and those pointing to the left inputs. For example:" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -4151,7 +4152,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -4164,7 +4165,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -4427,7 +4428,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -4443,7 +4444,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -4720,13 +4721,20 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 21, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "pivot_boundary_simp: 3. 1. 1. 3 iterations\n" + ] + }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -4972,10 +4980,17 @@ "metadata": {}, "output_type": "display_data" }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "lcomp_simp: 3. 3. 2 iterations\n" + ] + }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -5250,7 +5265,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -5263,7 +5278,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -5532,20 +5547,24 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "id_simp: 1. 1 iterations\n" + "id_simp: 1. 1 iterations\n", + "spider_simp: 1. 1 iterations\n", + "lcomp_simp: 1. 1. 2 iterations\n", + "id_simp: 3. 1 iterations\n", + "spider_simp: 1. 1 iterations\n" ] }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -5795,7 +5814,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Optimized T-count: 8\n" + "Optimized T-count: 18\n" ] } ], @@ -5817,13 +5836,20 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 24, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "gadget_simp: 4. 1 iterations\n" + ] + }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -6095,20 +6121,22 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "id_simp: 1. 1 iterations\n" + "id_simp: 1. 1 iterations\n", + "pivot_simp: 2. 1 iterations\n", + "lcomp_simp: 2. 2. 2 iterations\n" ] }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -6377,7 +6405,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 26, "metadata": {}, "outputs": [ { @@ -6398,7 +6426,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -6678,7 +6706,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -6691,7 +6719,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -6947,7 +6975,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -7203,7 +7231,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -7462,7 +7490,7 @@ "print(\"The optimized ZX-diagram:\")\n", "zx.draw(g)\n", "\n", - "new_circ = zx.extract.streaming_extract(g)\n", + "new_circ = zx.extract_circuit(g)\n", "print(\"The extracted circuit:\")\n", "zx.draw(new_circ)" ] @@ -7471,14 +7499,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Explaining how ``streaming_extract`` works is out of scope for this notebook for now. If you want to know more you can check out the paper [Graph-theoretic Simplification of Quantum Circuits with the ZX-calculus](https://arxiv.org/abs/1902.03178).\n", + "Explaining how ``extract_circuit`` works is out of scope for this notebook for now. If you want to know more you can check out the paper [Graph-theoretic Simplification of Quantum Circuits with the ZX-calculus](https://arxiv.org/abs/1902.03178) or the more recent (but more involved) [There and back again: A circuit extraction tale](https://arxiv.org/abs/2003.01664).\n", "\n", "As you can see, the extracted circuit looks quite different from the original circuit, so how can we be sure that they actually represent the same unitary? PyZX allows you to convert ZX-diagrams into the tensors they represent using numpy. In this way we can directly compare the unitaries and see that they are equal:" ] }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 28, "metadata": {}, "outputs": [ { @@ -7487,7 +7515,7 @@ "True" ] }, - "execution_count": 46, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -7508,7 +7536,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -7517,7 +7545,7 @@ "True" ] }, - "execution_count": 47, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -7537,32 +7565,32 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "``streaming_extract`` does not care about extracting a circuit that is in any way optimal. The amount of 2-qubit gates will therefore often be much higher than it needs to be. If you look at the end of the extracted circuit above you also see that it has some sequences of hadamards in a row that should be cancelled. PyZX offers a circuit optimization method that does this kind of hadamard and 2-qubit gate reduction:" + "``extract_circuit`` often produces circuits that are clearly not optimal as can be seen in the series of Hadamard gates at the end of the above extracted circuit. PyZX offers a circuit optimization method that takes care of this obvious kind of suboptimality:" ] }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 34, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Circuit on 5 qubits with 45 gates.\n", + "Circuit on 5 qubits with 70 gates.\n", " 8 is the T-count\n", - " 37 Cliffords among which \n", - " 24 2-qubit gates and 10 Hadamard gates.\n", - "Circuit on 5 qubits with 34 gates.\n", + " 62 Cliffords among which \n", + " 25 2-qubit gates and 34 Hadamard gates.\n", + "Circuit on 5 qubits with 35 gates.\n", " 8 is the T-count\n", - " 26 Cliffords among which \n", - " 24 2-qubit gates and 2 Hadamard gates.\n" + " 27 Cliffords among which \n", + " 25 2-qubit gates and 2 Hadamard gates.\n" ] }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -7811,7 +7839,7 @@ ], "source": [ "print(new_circ.to_basic_gates().stats())\n", - "optimized_circ = zx.optimize.basic_optimization(new_circ.to_basic_gates())\n", + "optimized_circ = zx.optimize.basic_optimization(new_circ.to_basic_gates(),do_swaps=False).to_basic_gates()\n", "print(optimized_circ.stats())\n", "zx.draw(optimized_circ)" ] @@ -7820,30 +7848,30 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "``basic_optimization`` commutes gates past Hadamards in order to find matching CNOT, CZ and Hadamard gates that can be cancelled. Depending on the circuit it can find significant reductions in the amount of Hadamard gates, which is useful for the next optimization routine.\n", + "``basic_optimization`` commutes gates past Hadamards in order to find matching CNOT, CZ and Hadamard gates that can be cancelled. Depending on the circuit it can find significant reductions in the amount of Hadamard gates, which is useful for the next optimization routine. Note that we gave it the argument `do_swaps=False`. When this is instead set to True, it employs more powerful optimization techniques involving transforming adjacent CNOT gates into SWAPs. While for larger circuits this often leads to better results, for the above circuit it actually increases the 2-qubit gate-count (from 25 to 27).\n", "\n", "As you can see, the optimized circuit only contains 2 Hadamard gates, and in fact the leftmost Hadamard gate could be commuted past the CNOTs and CZs to its left so that the entire interior of the circuit is free of Hadamards. Such a Hadamard-free circuit is called a *phase polynomial* circuit, and there are specific techniques for optimizing these types of circuits. PyZX offers a method that finds phase polynomial sub-circuits and runs an optimization routine on them:" ] }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 36, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Circuit on 5 qubits with 27 gates.\n", + "Circuit on 5 qubits with 30 gates.\n", " 8 is the T-count\n", - " 19 Cliffords among which \n", - " 14 2-qubit gates and 2 Hadamard gates.\n" + " 22 Cliffords among which \n", + " 17 2-qubit gates and 2 Hadamard gates.\n" ] }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -8091,7 +8119,7 @@ } ], "source": [ - "final_circ = zx.optimize.phase_block_optimize(optimized_circ)\n", + "final_circ = zx.optimize.phase_block_optimize(optimized_circ).to_basic_gates()\n", "final_circ = zx.optimize.basic_optimization(final_circ) # We call this again, as it does some extra processing\n", "print(final_circ.stats())\n", "zx.draw(final_circ)" @@ -8106,7 +8134,7 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 37, "metadata": {}, "outputs": [ { @@ -8115,7 +8143,7 @@ "True" ] }, - "execution_count": 52, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -8133,7 +8161,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 38, "metadata": {}, "outputs": [ { @@ -8145,7 +8173,6 @@ "qreg q[5];\n", "s q[0];\n", "cz q[0], q[1];\n", - "z q[1];\n", "cz q[1], q[2];\n", "s q[2];\n", "cx q[3], q[2];\n", @@ -8165,11 +8192,15 @@ "cx q[4], q[2];\n", "t q[0];\n", "t q[2];\n", - "cx q[1], q[2];\n", + "cx q[3], q[2];\n", "cx q[4], q[0];\n", "h q[4];\n", "t q[0];\n", "cx q[1], q[0];\n", + "cx q[3], q[1];\n", + "cx q[1], q[2];\n", + "cx q[3], q[1];\n", + "z q[1];\n", "\n" ] } @@ -8197,7 +8228,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 39, "metadata": {}, "outputs": [ { @@ -8210,7 +8241,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -8466,7 +8497,7 @@ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -8732,7 +8763,7 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 40, "metadata": {}, "outputs": [ { @@ -8741,7 +8772,7 @@ "True" ] }, - "execution_count": 57, + "execution_count": 40, "metadata": {}, "output_type": "execute_result" } diff --git a/demos/Challenge_circuit_extraction.ipynb b/demos/Challenge_circuit_extraction.ipynb index 174a1790..b571d886 100644 --- a/demos/Challenge_circuit_extraction.ipynb +++ b/demos/Challenge_circuit_extraction.ipynb @@ -60,20 +60,13 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "This function will be removed. Please use zx.draw or zx.draw_d3 instead.\n" - ] - }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -321,8 +314,8 @@ } ], "source": [ - "c1 = zx.extract.streaming_extract(g1.copy())\n", - "zx.d3.draw(c1.to_graph())" + "c1 = zx.extract_circuit(g1.copy())\n", + "zx.draw(c1.to_graph())" ] }, { @@ -334,7 +327,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -364,22 +357,24 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 8, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "***Error in extraction***: Did not find any completely reducable row\n" + "ename": "Exception", + "evalue": "No extractable vertex found. Something went wrong", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mException\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mc2\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mzx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mextract_circuit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mg2\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;32m~\\Documents\\Projects\\pyzx\\pyzx\\extract.py\u001b[0m in \u001b[0;36mextract_circuit\u001b[1;34m(g, optimize_czs, optimize_cnots, quiet)\u001b[0m\n\u001b[0;32m 451\u001b[0m \u001b[0mw\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mneighbours\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mj\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mj\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mrow\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mrow\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mj\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 452\u001b[0m \u001b[0mgood_verts\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mv\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mw\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 453\u001b[1;33m \u001b[1;32mif\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mgood_verts\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"No extractable vertex found. Something went wrong\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 454\u001b[0m \u001b[0mhads\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 455\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mv\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mw\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mgood_verts\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m \u001b[1;31m# Update frontier vertices\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mException\u001b[0m: No extractable vertex found. Something went wrong" ] } ], "source": [ - "try:\n", - " c2 = zx.extract.streaming_extract(g2.copy())\n", - "except ValueError as e:\n", - " print(\"***Error in extraction***: %s\" % e)" + "c2 = zx.extract_circuit(g2.copy())" ] }, { @@ -391,7 +386,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "metadata": {}, "outputs": [ { diff --git a/demos/Optimising almost-Clifford circuits.ipynb b/demos/Optimising almost-Clifford circuits.ipynb index 5b7cb829..1898ef97 100644 --- a/demos/Optimising almost-Clifford circuits.ipynb +++ b/demos/Optimising almost-Clifford circuits.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -39,7 +39,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -73,7 +73,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -137,13 +137,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -397,21 +397,21 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "11\n", + "9\n", "True\n" ] }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -670,14 +670,14 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "def opt_circuit(c):\n", " g = c.to_graph()\n", " zx.simplify.interior_clifford_simp(g,quiet=True)\n", - " c2 = zx.extract.streaming_extract(g)\n", + " c2 = zx.extract_circuit(g)\n", " return zx.optimize.basic_optimization(c2.to_basic_gates()).to_basic_gates()\n", "def part_opt_circuit(c):\n", " cs = split_circ_on_T(c)\n", @@ -689,7 +689,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -735,32 +735,14 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "0.0;0.015;" - ] - }, - { - "ename": "KeyboardInterrupt", - "evalue": "", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mt_prob\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;34m';'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[0mdepth\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m800\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m \u001b[0mys\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mzs\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mgenerate_dataset\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mqubits\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mdepth\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mcnot_prob\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m0.3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mt_prob\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mt_prob\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mreps\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mreps\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 12\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0my\u001b[0m \u001b[1;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mys\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0myys\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 13\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mz\u001b[0m \u001b[1;32min\u001b[0m \u001b[0menumerate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mzs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mzzs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mz\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m\u001b[0m in \u001b[0;36mgenerate_dataset\u001b[1;34m(qubits, depth, cnot_prob, t_prob, reps, two_q)\u001b[0m\n\u001b[0;32m 11\u001b[0m \u001b[0mc0\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mc\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 12\u001b[0m \u001b[0mc0\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mzx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimize\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbasic_optimization\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mc0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mto_basic_gates\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 13\u001b[1;33m \u001b[0mc1\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mpart_opt_circuit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mc\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 14\u001b[0m \u001b[0mc2\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mopt_circuit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mc\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 15\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m\u001b[0m in \u001b[0;36mpart_opt_circuit\u001b[1;34m(c)\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mi\u001b[0m \u001b[1;33m%\u001b[0m \u001b[1;36m2\u001b[0m \u001b[1;33m==\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[0mcs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mopt_circuit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcs\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mzx\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moptimize\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mbasic_optimization\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmerge_circ\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mto_basic_gates\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;32m~\\Documents\\Projects\\pyzx\\pyzx\\optimize.py\u001b[0m in \u001b[0;36mbasic_optimization\u001b[1;34m(circuit, do_swaps, quiet)\u001b[0m\n\u001b[0;32m 46\u001b[0m \u001b[1;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Input must be a Circuit\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 47\u001b[0m \u001b[0mo\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mOptimizer\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 48\u001b[1;33m \u001b[1;32mreturn\u001b[0m \u001b[0mo\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparse_circuit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdo_swaps\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mdo_swaps\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mquiet\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mquiet\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 49\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 50\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0mtoggle_element\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ml\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mlist\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0me\u001b[0m\u001b[1;33m:\u001b[0m\u001b[0mobject\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m->\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m~\\Documents\\Projects\\pyzx\\pyzx\\optimize.py\u001b[0m in \u001b[0;36mparse_circuit\u001b[1;34m(self, separate_correction, max_iterations, do_swaps, quiet)\u001b[0m\n\u001b[0;32m 125\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mg\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mcorrection\u001b[0m\u001b[1;33m:\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgates\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mto_basic_gates\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 126\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgates\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mreversed\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgates\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 127\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcorrection\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparse_forward\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 128\u001b[0m \u001b[0mi\u001b[0m \u001b[1;33m+=\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 129\u001b[0m \u001b[0ms\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mstats\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m~\\Documents\\Projects\\pyzx\\pyzx\\optimize.py\u001b[0m in \u001b[0;36mparse_forward\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 152\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgcount\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 153\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mg\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcircuit\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mgates\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 154\u001b[1;33m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mparse_gate\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mg\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 155\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mt\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mhadamards\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 156\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0madd_hadamard\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mt\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m~\\Documents\\Projects\\pyzx\\pyzx\\optimize.py\u001b[0m in \u001b[0;36mparse_gate\u001b[1;34m(self, g)\u001b[0m\n\u001b[0;32m 396\u001b[0m \u001b[0mg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 397\u001b[0m \u001b[1;31m# If we have some SWAPs recorded we need to change the target/control of the gate accordingly\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 398\u001b[1;33m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtarget\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpermutation\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpermutation\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtarget\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 399\u001b[0m \u001b[0mt\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtarget\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 400\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mname\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'CZ'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'CNOT'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m~\\Documents\\Projects\\pyzx\\pyzx\\optimize.py\u001b[0m in \u001b[0;36m\u001b[1;34m(.0)\u001b[0m\n\u001b[0;32m 396\u001b[0m \u001b[0mg\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 397\u001b[0m \u001b[1;31m# If we have some SWAPs recorded we need to change the target/control of the gate accordingly\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 398\u001b[1;33m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtarget\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mi\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpermutation\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpermutation\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mi\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtarget\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 399\u001b[0m \u001b[0mt\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtarget\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 400\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mg\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mname\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m(\u001b[0m\u001b[1;34m'CZ'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'CNOT'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mKeyboardInterrupt\u001b[0m: " + "0.0;0.015;0.03;0.045;0.06;0.075;0.09;0.105;0.12;0.135;0.15;" ] } ], @@ -789,7 +771,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 9, "metadata": { "scrolled": false }, @@ -806,1535 +788,1270 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ - "\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", - " \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", - " \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", - " \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", - " \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", - " \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" + "\r\n", + "\r\n", + "\r\n", + "\r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + "\r\n" ], "text/plain": [ "
" @@ -2359,1586 +2076,1280 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ - "\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", - " \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", - " \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", - " \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", - " \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", - " \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" + "\r\n", + "\r\n", + "\r\n", + "\r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + " \r\n", + "\r\n" ], "text/plain": [ "
" diff --git a/demos/STRING2019.ipynb b/demos/STRING2019.ipynb index 71d36228..e01f0ce3 100644 --- a/demos/STRING2019.ipynb +++ b/demos/STRING2019.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -13,13 +13,13 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -273,16 +273,16 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "1" + "2" ] }, - "execution_count": 5, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -293,13 +293,13 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -553,16 +553,16 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "1" + "2" ] }, - "execution_count": 7, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -574,13 +574,13 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -834,7 +834,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -857,7 +857,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -878,13 +878,13 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -1145,13 +1145,13 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -1413,23 +1413,23 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Circuit on 4 qubits with 41 gates.\n", + "Circuit on 4 qubits with 44 gates.\n", " 4 is the T-count\n", - " 37 Cliffords among which \n", - " 21 2-qubit gates and 12 Hadamard gates.\n" + " 40 Cliffords among which \n", + " 22 2-qubit gates and 14 Hadamard gates.\n" ] }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -1677,14 +1677,14 @@ } ], "source": [ - "c2 = zx.extract.streaming_extract(g.copy())\n", + "c2 = zx.extract_circuit(g.copy())\n", "print(c2.to_basic_gates().stats())\n", "zx.draw(c2.to_graph())" ] }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -1693,7 +1693,7 @@ "True" ] }, - "execution_count": 15, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -1704,7 +1704,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -1714,7 +1714,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -1723,7 +1723,7 @@ "False" ] }, - "execution_count": 17, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } diff --git a/demos/T-count Benchmark.ipynb b/demos/T-count Benchmark.ipynb index a0202bd0..4afc6dc0 100644 --- a/demos/T-count Benchmark.ipynb +++ b/demos/T-count Benchmark.ipynb @@ -80,7 +80,7 @@ " self.time_simpl = time.time() - t\n", " t = time.time()\n", " c_opt = zx.Circuit.from_graph(g).split_phase_gates().to_basic_gates()\n", - " #c_opt = zx.extract.streaming_extract(g).to_basic_gates()\n", + " #c_opt = zx.extract_circuit(g).to_basic_gates()\n", " c_opt = zx.optimize.basic_optimization(c_opt).to_basic_gates()\n", " self.c_opt = c_opt\n", " if validate:\n", @@ -96,7 +96,7 @@ " self.extracts = True\n", " self.time_extr = 0.0\n", "# try: \n", - "# c2 = zx.extract.streaming_extract(g,quiet=True)\n", + "# c2 = zx.extract_circuit(g,quiet=True)\n", "# self.time_extr = time.time() - t\n", "# except Exception:\n", "# self.extracts = False\n", diff --git a/demos/example-gtsimp.ipynb b/demos/example-gtsimp.ipynb index 03c87eaa..23c751e2 100644 --- a/demos/example-gtsimp.ipynb +++ b/demos/example-gtsimp.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -87,13 +87,13 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -354,13 +354,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -622,23 +622,23 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Circuit on 4 qubits with 41 gates.\n", + "Circuit on 4 qubits with 44 gates.\n", " 4 is the T-count\n", - " 37 Cliffords among which \n", - " 21 2-qubit gates and 12 Hadamard gates.\n" + " 40 Cliffords among which \n", + " 22 2-qubit gates and 14 Hadamard gates.\n" ] }, { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -886,7 +886,7 @@ } ], "source": [ - "c = zx.extract.streaming_extract(g.copy())\n", + "c = zx.extract_circuit(g.copy())\n", "print(c.to_basic_gates().stats())\n", "zx.draw(c.to_graph())" ] diff --git a/demos/gettingstarted.ipynb b/demos/gettingstarted.ipynb index b94e8f4f..1d82784e 100644 --- a/demos/gettingstarted.ipynb +++ b/demos/gettingstarted.ipynb @@ -11,7 +11,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -29,7 +29,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -56,252 +56,252 @@ " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", " \r\n", " \r\n", - " \r\n", + " \r\n", " \r\n", " \r\n", " \r\n", @@ -1697,7 +1697,7 @@ "
" ] }, - "execution_count": 6, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -1721,7 +1721,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -1750,7 +1750,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -1759,7 +1759,7 @@ "1" ] }, - "execution_count": 8, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -1771,7 +1771,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -2045,13 +2045,13 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "55e0a5587f674a48b96367fea8ac8dcc", + "model_id": "5f307792ffff42949c013992c366a5eb", "version_major": 2, "version_minor": 0 }, @@ -2109,18 +2109,18 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Even though this graph is a lot compacter than the one we started out with, it no longer looks like a circuit. To fix this we need to be clever." + "Even though this graph is a lot compacter than the one we started out with, it no longer looks like a circuit. To fix this we need to be clever and *extract* a circuit from the ZX-diagram:" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -2370,7 +2370,7 @@ "source": [ "circ2 = g.copy()\n", "circ2.normalise()\n", - "circ2 = zx.extract.streaming_extract(circ2)\n", + "circ2 = zx.extract_circuit(circ2)\n", "zx.draw(circ2)" ] }, @@ -2383,7 +2383,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -2392,7 +2392,7 @@ "True" ] }, - "execution_count": 19, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -2413,7 +2413,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -2421,36 +2421,36 @@ "output_type": "stream", "text": [ "Inputs: 0:Qbit, 1:Qbit, 2:Qbit, 3:Qbit\n", - "QGate[\"H\"](3) with nocontrol\n", - "QRot[\"exp(-i%Z)\",0.7853981633974483](3)\n", - "QGate[\"H\"](1) with nocontrol\n", - "QRot[\"exp(-i%Z)\",1.5707963267948966](1)\n", - "QGate[\"Z\"](1) with controls=[+2] with nocontrol\n", - "QGate[\"Z\"](1) with controls=[+3] with nocontrol\n", - "QGate[\"Z\"](0) with controls=[+1] with nocontrol\n", + "QGate[\"not\"](3) with controls=[+2] with nocontrol\n", + "QGate[\"not\"](2) with controls=[+3] with nocontrol\n", + "QGate[\"not\"](3) with controls=[+2] with nocontrol\n", + "QGate[\"not\"](1) with controls=[+0] with nocontrol\n", + "QGate[\"not\"](0) with controls=[+1] with nocontrol\n", + "QGate[\"not\"](1) with controls=[+0] with nocontrol\n", + "QGate[\"H\"](2) with nocontrol\n", "QGate[\"H\"](0) with nocontrol\n", - "QRot[\"exp(-i%Z)\",1.5707963267948966](0)\n", - "QGate[\"H\"](1) with nocontrol\n", - "QRot[\"exp(-i%Z)\",0.7853981633974483](1)\n", - "QGate[\"Z\"](0) with controls=[+2] with nocontrol\n", - "QGate[\"Z\"](0) with controls=[+3] with nocontrol\n", "QGate[\"Z\"](1) with controls=[+0] with nocontrol\n", - "QGate[\"H\"](3) with nocontrol\n", - "QRot[\"exp(-i%Z)\",1.5707963267948966](3)\n", - "QGate[\"Z\"](3) with controls=[+2] with nocontrol\n", - "QGate[\"Z\"](1) with controls=[+3] with nocontrol\n", + "QGate[\"H\"](1) with nocontrol\n", + "QGate[\"Z\"](2) with controls=[+1] with nocontrol\n", + "QGate[\"Z\"](2) with controls=[+0] with nocontrol\n", + "QRot[\"exp(-i%Z)\",0.7853981633974483](2)\n", "QGate[\"H\"](2) with nocontrol\n", - "QRot[\"exp(-i%Z)\",1.5707963267948966](2)\n", "QGate[\"Z\"](3) with controls=[+2] with nocontrol\n", - "QGate[\"H\"](2) with nocontrol\n", + "QGate[\"Z\"](3) with controls=[+1] with nocontrol\n", + "QGate[\"Z\"](3) with controls=[+0] with nocontrol\n", + "QRot[\"exp(-i%Z)\",1.5707963267948966](0)\n", + "QGate[\"H\"](0) with nocontrol\n", + "QGate[\"H\"](3) with nocontrol\n", + "QGate[\"Z\"](3) with controls=[+2] with nocontrol\n", + "QGate[\"Z\"](2) with controls=[+0] with nocontrol\n", + "QGate[\"Z\"](1) with controls=[+0] with nocontrol\n", + "QRot[\"exp(-i%Z)\",0.7853981633974483](0)\n", "QGate[\"H\"](0) with nocontrol\n", + "QRot[\"exp(-i%Z)\",1.5707963267948966](1)\n", "QGate[\"H\"](1) with nocontrol\n", - "QGate[\"not\"](1) with controls=[+0] with nocontrol\n", - "QGate[\"not\"](0) with controls=[+1] with nocontrol\n", - "QGate[\"not\"](1) with controls=[+0] with nocontrol\n", - "QGate[\"not\"](3) with controls=[+2] with nocontrol\n", - "QGate[\"not\"](2) with controls=[+3] with nocontrol\n", - "QGate[\"not\"](3) with controls=[+2] with nocontrol\n", + "QRot[\"exp(-i%Z)\",1.5707963267948966](2)\n", + "QRot[\"exp(-i%Z)\",1.5707963267948966](3)\n", + "QGate[\"H\"](3) with nocontrol\n", "Outputs: 0:Qbit, 1:Qbit, 2:Qbit, 3:Qbit\n" ] } @@ -2468,13 +2468,13 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -2731,13 +2731,13 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" @@ -2995,28 +2995,28 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We use a different extraction procedure for this circuit. Instead of producing a ZX-graph as output we get a description as a circuit:" + "Again, let us extract a circuit from this diagram:" ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Circuit on 6 qubits with 55 gates.\n", + "Circuit on 6 qubits with 62 gates.\n", " 8 is the T-count\n", - " 47 Cliffords among which \n", - " 27 2-qubit gates and 16 Hadamard gates.\n" + " 54 Cliffords among which \n", + " 28 2-qubit gates and 22 Hadamard gates.\n" ] } ], "source": [ "g2 = g.copy()\n", - "c = zx.extract.streaming_extract(g2)\n", + "c = zx.extract_circuit(g2)\n", "print(c.stats())" ] }, @@ -3029,13 +3029,13 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
\n", + "
\n", "\n", "" ], @@ -3295,7 +3295,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -3304,13 +3304,14 @@ "True" ] }, - "execution_count": 34, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "zx.compare_tensors(c.to_tensor(), circ.to_tensor(),preserve_scalar=False)" + "# We can just feed the Circuit objects directly to compare_tensors\n", + "zx.compare_tensors(c, circ)" ] }, { @@ -3322,7 +3323,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -3332,67 +3333,72 @@ "OPENQASM 2.0;\n", "include \"qelib1.inc\";\n", "qreg q[6];\n", - "rz(0.75*pi) q[1];\n", - "rz(1.5*pi) q[3];\n", - "rz(0.5*pi) q[4];\n", - "h q[2];\n", - "h q[0];\n", - "cz q[1], q[4];\n", - "cz q[3], q[4];\n", - "cz q[3], q[5];\n", - "cz q[4], q[5];\n", - "cz q[5], q[2];\n", - "cz q[1], q[0];\n", - "cz q[4], q[0];\n", - "h q[2];\n", - "rz(0.75*pi) q[2];\n", + "cx q[2], q[5];\n", + "cx q[5], q[2];\n", + "cx q[2], q[5];\n", + "cx q[1], q[4];\n", + "cx q[4], q[1];\n", + "cx q[1], q[4];\n", "h q[5];\n", - "rz(1.25*pi) q[5];\n", + "h q[4];\n", + "h q[3];\n", "h q[1];\n", - "rz(0.75*pi) q[1];\n", - "cz q[4], q[2];\n", - "cz q[3], q[5];\n", - "cz q[4], q[5];\n", + "h q[1];\n", + "h q[3];\n", "cz q[2], q[5];\n", - "cz q[2], q[0];\n", - "cx q[4], q[3];\n", - "cx q[2], q[4];\n", + "cz q[2], q[3];\n", + "cz q[1], q[2];\n", "h q[2];\n", + "h q[5];\n", + "cz q[2], q[5];\n", + "cz q[2], q[3];\n", + "cz q[1], q[2];\n", "rz(1.25*pi) q[2];\n", + "h q[0];\n", "h q[2];\n", - "rz(0.5*pi) q[2];\n", - "cz q[3], q[2];\n", - "cx q[2], q[3];\n", - "cx q[4], q[5];\n", "h q[4];\n", - "rz(0.25*pi) q[4];\n", - "cz q[3], q[4];\n", + "cz q[1], q[5];\n", + "cz q[1], q[4];\n", + "cz q[1], q[3];\n", + "cz q[1], q[2];\n", + "cz q[0], q[1];\n", + "rz(0.5*pi) q[1];\n", + "h q[1];\n", + "cz q[1], q[3];\n", + "rz(1.5*pi) q[3];\n", + "h q[3];\n", + "cz q[0], q[5];\n", "cz q[0], q[4];\n", - "cz q[4], q[1];\n", + "cz q[0], q[3];\n", "h q[0];\n", - "rz(0.25*pi) q[0];\n", - "h q[3];\n", - "cz q[5], q[0];\n", - "cz q[4], q[0];\n", + "cx q[0], q[2];\n", + "cz q[3], q[5];\n", + "cz q[2], q[5];\n", + "cz q[0], q[5];\n", + "rz(0.75*pi) q[5];\n", "h q[5];\n", "rz(1.25*pi) q[5];\n", - "cz q[5], q[4];\n", "h q[5];\n", - "cz q[5], q[0];\n", + "cx q[5], q[1];\n", + "cz q[2], q[3];\n", + "rz(1.25*pi) q[2];\n", + "h q[2];\n", + "cz q[0], q[3];\n", + "cz q[0], q[2];\n", + "rz(0.75*pi) q[4];\n", + "rz(0.25*pi) q[0];\n", + "h q[4];\n", "h q[0];\n", - "rz(0.5*pi) q[0];\n", + "cz q[3], q[5];\n", + "cz q[3], q[4];\n", + "cz q[1], q[5];\n", + "rz(0.5*pi) q[5];\n", "h q[5];\n", + "rz(0.75*pi) q[4];\n", + "rz(0.25*pi) q[3];\n", "h q[2];\n", + "rz(0.5*pi) q[0];\n", "h q[0];\n", - "cx q[1], q[3];\n", - "cx q[3], q[1];\n", - "cx q[1], q[3];\n", - "cx q[2], q[5];\n", - "cx q[5], q[2];\n", - "cx q[2], q[5];\n", - "cx q[3], q[4];\n", - "cx q[4], q[3];\n", - "cx q[3], q[4];\n", "\n" ] } diff --git a/pyzx/__init__.py b/pyzx/__init__.py index 40e26bb1..a9540468 100644 --- a/pyzx/__init__.py +++ b/pyzx/__init__.py @@ -24,6 +24,7 @@ from .drawing import * from .simplify import * from .optimize import * +from .extract import * from .io import * from .tensor import * from .circuit.qasmparser import qasm diff --git a/pyzx/extract.py b/pyzx/extract.py index 1b0b64b8..28939048 100644 --- a/pyzx/extract.py +++ b/pyzx/extract.py @@ -17,7 +17,7 @@ from __future__ import print_function -__all__ = ['streaming_extract', 'modified_extract'] +__all__ = ['extract_circuit'] from fractions import Fraction import itertools @@ -35,70 +35,6 @@ def bi_adj(g, vs, ws): return Mat2([[1 if g.connected(v,w) else 0 for v in vs] for w in ws]) -def cut_rank(g, left, right): - return bi_adj(g, left, right).rank() - -def cut_edges(g, left, right, available=None): - m = bi_adj(g, left, right) - max_r = max(g.row(v) for v in left) - for v in g.vertices(): - r = g.row(v) - if (r > max_r): - g.set_row(v, r+2) - x,y = m.factor() - - for v1 in left: - for v2 in right: - if (g.connected(v1,v2)): - g.remove_edge(g.edge(v1,v2)) - - cut_rank = y.rows() - - #g.add_vertices(2*cut_rank) - left_verts = [] - right_verts = [] - - if available == None: - qs = range(cut_rank) - else: - qs = available - - for i in qs: - v1 = g.add_vertex(VertexType.Z,i,max_r+1) - v2 = g.add_vertex(VertexType.Z,i,max_r+2) - #v = vi+cut_rank+i - #g.add_edge((vi+i,v)) - g.add_edge((v1,v2),EdgeType.HADAMARD) - left_verts.append(v1) - right_verts.append(v2) - #g.set_edge_type(g.edge(vi+i,v), EdgeType.HADAMARD) - - for i in range(y.rows()): - for j in range(y.cols()): - if (y.data[i][j]): - g.add_edge((left[j],left_verts[i]),EdgeType.HADAMARD) - #g.add_edge((left[j], vi + i)) - #g.set_edge_type(g.edge(left[j], vi + i), EdgeType.HADAMARD) - for i in range(x.rows()): - for j in range(x.cols()): - if (x.data[i][j]): - g.add_edge((right_verts[j],right[i]),EdgeType.HADAMARD) - #g.add_edge((vi + cut_rank + j, right[i])) - #g.set_edge_type(g.edge(vi + cut_rank + j, right[i]), EdgeType.HADAMARD) - return left_verts - - -def unspider_by_row(g, v): - r = g.row(v) - w = g.add_vertex(VertexType.Z,g.qubit(v),r-1) - for n in list(g.neighbours(v)): - if g.row(n) < r: - e = g.edge(n,v) - g.add_edge((n,w), edgetype=g.edge_type(e)) - g.remove_edge(e) - g.add_edge((w, v)) - return w - def connectivity_from_biadj(g, m, left, right, edgetype=EdgeType.HADAMARD): for i in range(len(right)): for j in range(len(left)): @@ -107,503 +43,9 @@ def connectivity_from_biadj(g, m, left, right, edgetype=EdgeType.HADAMARD): elif not m.data[i][j] and g.connected(right[i],left[j]): g.remove_edge((right[i],left[j])) -def streaming_extract(g, allow_ancillae=False, quiet=True, stopcount=-1): - """Given a graph put into semi-normal form by :func:`pyzx.simplify.full_reduce`, - extracts an equivalent :class:`~pyzx.circuit.Circuit`. - Uses a version of the algorithm in `this paper `__. - For large graphs, this function can take a couple of minutes to finish. - - Args: - g: The graph from which a circuit is to be extracted. - allow_ancillae: Experimental feature to allow extraction for more types of diagrams. Results in post-selected circuits. - quiet: Whether to print some progress indicators. - stopcount: If set to a positive integer, stops the extraction after this many gates have been extracted. Useful for debugging or stopping the process when it takes too long. - - Note: - The graph ``g`` is modified in-place during extraction. If you wish to preserve it, call this function with a copy of it: ``streaming_extract(g.copy())``. - """ - g.normalise() - qs = g.qubits() # We are assuming that these are objects that update... - rs = g.rows() # ...to reflect changes to the graph, so that when... - ty = g.types() # ... g.set_row/g.set_qubit is called, these things update directly to reflect that - phases = g.phases() - c = Circuit(g.qubit_count()) - leftrow = 1 - maxq = max(qs.values()) + 1 - - nodestotal = tcount(g) - nodesparsed = 0 - nodesmarker = 10 - - # special_nodes contains the ParityPhase like nodes - special_nodes = {} - for v in g.vertices(): - if len(list(g.neighbours(v))) == 1 and v not in g.inputs and v not in g.outputs: - n = list(g.neighbours(v))[0] - special_nodes[n] = v - if rs[v] > 1: - g.set_row(v, rs[v]+20) - - tried_id_simp = False - while True: - left = [v for v in g.vertices() if rs[v] == leftrow] - boundary_verts = [] - right = set() - good_verts = [] - good_neighs = [] - postselects = [] - for v in left: - # First we add the gates to the circuit that can be processed now, - # and we simplify the graph to represent this. - q = qs[v] - phase = phases[v] - t = ty[v] - neigh = [w for w in g.neighbours(v) if rs[w] 2: nodesparsed += 1 - if t == VertexType.Z: c.add_gate("ZPhase", q, phase=phase) - else: c.add_gate("XPhase", q, phase=phase) - g.set_phase(v, 0) - for v in left: - q = qs[v] - t = ty[v] - neigh = [w for w in g.neighbours(v) if rs[w]==leftrow and wleftrow] - right.update(d) - if len(d) == 0: - if not allow_ancillae: raise TypeError("Not circuit like") - else: - postselects.append(v) - if len(d) == 1: # Only connected to one node in its future - if ty[d[0]] != VertexType.BOUNDARY: # which is not an output - good_verts.append(v) # So we can make progress - good_neighs.append(d[0]) - else: # This node is done processing, since it is directly (and only) connected to an output - boundary_verts.append(v) - right.remove(d[0]) - for v in postselects: - if not quiet: print("postselect", v, qs[v]) - c.add_gate("PostSelect", qs[v]) - left.remove(v) - g.set_row(v, leftrow-0.5) - if qs[v] == maxq - 1: - maxq = maxq -1 - if not good_verts: # There are no 'easy' nodes we can use to progress - if all(ty[v] == VertexType.BOUNDARY for v in right): break # Actually we are done, since only outputs are left - for v in boundary_verts: left.remove(v) # We don't care about the nodes only connected to outputs - have_removed_gadgets = False - for n in right.intersection(special_nodes): # Neighbours that are phase gadgets - targets = set(g.neighbours(n)) - targets.remove(special_nodes[n]) - if targets.issubset(left): # Only connectivity on the lefthandside, so we can extract it - nphase = phases[n] - if nphase not in (0,1): - raise Exception("Can't parse ParityPhase with non-Pauli Phase") - phase = phases[special_nodes[n]] - c.add_gate("ParityPhase", phase*(-1 if nphase else 1), *[qs[t] for t in targets]) - g.remove_vertices([special_nodes[n],n]) - nodesparsed += 1 - right.remove(n) - del special_nodes[n] - have_removed_gadgets = True - if stopcount != -1 and len(c.gates) > stopcount: return c - if have_removed_gadgets: continue - right = list(right) - m = bi_adj(g,right,left) - m2 = m.copy() - m2.gauss(full_reduce=True) - if not any(sum(l)==1 for l in m2.data): - if not tried_id_simp: - tried_id_simp = True - i = id_simp(g, matchf=lambda v: rs[v]>leftrow, quiet=True) - if i: - if not quiet: print("id_simp found some matches") - m = match_spider_parallel(g, matchf=lambda e: rs[g.edge_s(e)]>=leftrow and rs[g.edge_t(e)]>=leftrow) - m = [(v1,v2) if v1 in left else (v2,v1) for v1,v2 in m] - if not quiet and m: print("spider fusion found some matches") - etab, rem_verts, not_needed1, not_needed2 = spider(g, m) - g.add_edge_table(etab) - g.remove_vertices(rem_verts) - continue - try: - gates, lr = handle_phase_gadget(g, left, set(right), special_nodes, quiet=quiet) - except ValueError: - if not allow_ancillae: - raise - raise Exception - gates, maxq = find_ancilla_qubits(g, left, set(right), special_nodes, maxq, quiet=quiet) - c.gates.extend(gates) - continue - c.gates.extend(gates) - nodesparsed += 1 - tried_id_simp = False - if lr > leftrow: - for v in boundary_verts: - g.set_row(v, lr) - leftrow = lr - continue - sequence = greedy_reduction(m) # Find the optimal set of CNOTs we can apply to get a frontier we can work with - if not isinstance(sequence, list): # Couldn't find any reduction, hopefully we can fix this - right = set(right) - gates, success = try_greedy_cut(g, left, right, right.difference(special_nodes), quiet=quiet) - if success: - c.gates.extend(gates) - continue - raise Exception("We should never get here") - - if not quiet: print("Greedy reduction with {:d} CNOTs".format(len(sequence))) - for control, target in sequence: - c.add_gate("CNOT", qs[left[target]], qs[left[control]]) - # If a control is connected to an output, we need to add a new node. - for v in g.neighbours(left[control]): - if v in g.outputs: - #print("Adding node before output") - q = qs[v] - r = rs[v] - w = g.add_vertex(VertexType.Z,q,r-1) - e = g.edge(left[control],v) - et = g.edge_type(e) - g.remove_edge(e) - g.add_edge((left[control],w),EdgeType.HADAMARD) - g.add_edge((w,v),toggle_edge(et)) - k = right.index(v) - right[k] = w - break - for k in range(len(m.data[control])): # We update the graph to represent the extraction of a CNOT - if not m.data[control][k]: continue - if m.data[target][k]: g.remove_edge((left[target],right[k])) - else: g.add_edge((left[target],right[k]), EdgeType.HADAMARD) - m.row_add(control, target) - for v in left: - d = [w for w in g.neighbours(v) if rs[w]>leftrow] - if len(d) == 1 and ty[d[0]] != VertexType.BOUNDARY: - good_verts.append(v) - good_neighs.append(d[0]) - if not good_verts: continue - - for v in g.vertices(): - if rs[v] < leftrow: continue - if v in good_verts: continue - g.set_row(v,rs[v]+1) # Push the frontier one layer up - for i,v in enumerate(good_neighs): - g.set_row(v,leftrow+1) # Bring the new nodes of the frontier to the correct position - g.set_qubit(v,qs[good_verts[i]]) - - tried_id_simp = False - - if not quiet and nodesparsed > nodesmarker: - print("{:d}/{:d}".format(nodesparsed, nodestotal)) - nodesmarker = int(round(nodesparsed-5,-1)) - nodesmarker += 10 - leftrow += 1 - if stopcount != -1 and len(c.gates) > stopcount: return c - - swap_map = {} - leftover_swaps = False - for v in left: # Finally, check for the last layer of Hadamards, and see if swap gates need to be applied. - q = qs[v] - neigh = [w for w in g.neighbours(v) if rs[w]>leftrow] - if len(neigh) != 1: - raise TypeError("Algorithm failed: Not fully reducable") - return c - n = neigh[0] - if ty[n] != VertexType.BOUNDARY: - raise TypeError("Algorithm failed: Not fully reducable") - return c - if g.edge_type(g.edge(n,v)) == EdgeType.HADAMARD: - c.add_gate("HAD", q) - g.set_edge_type(g.edge(n,v),EdgeType.SIMPLE) - if qs[n] != q: leftover_swaps = True - swap_map[q] = qs[n] - if leftover_swaps: - for t1, t2 in permutation_as_swaps(swap_map): - c.add_gate("SWAP", t1, t2) - return c - - -def try_greedy_cut(g, left, right, candidates, quiet=True): - q = len(left) - left = list(left) - # Take care nothing is connected directly to an output - for w in right.copy(): - if w in g.outputs: - w2 = g.add_vertex(VertexType.Z, g.qubit(w), g.row(w)-1) - n = list(g.neighbours(w))[0] # Outputs should have unique neighbours - e = g.edge(n,w) - et = g.edge_type(e) - g.remove_edge(e) - g.add_edge((n,w2),EdgeType.HADAMARD) - g.add_edge((w2,w),toggle_edge(et)) - right.remove(w) - right.add(w2) - if w in candidates: - candidates.remove(w) - candidates.add(w2) - - right = list(right) - # We want to figure out which vertices in candidates are 'pivotable' - # That is, that removing them will decrease the cut rank of the remainder - m = bi_adj(g, right, left) - m.gauss(full_reduce=True) # Gaussian elimination doesn't change this property - good_nodes = [] - for r in m.data: - if sum(r) == 1: # Exactly one nonzero value, so removing the column with the nonzero value... - i = next(i for i in range(len(r)) if r[i]) # ...decreases the rank of the matrix - w = right[i] - if w in candidates: - good_nodes.append(w) - if not good_nodes: - return [], False - right = [w for w in right if w not in good_nodes] - - new_right = cut_edges(g, left, right) - leftrow = g.row(left[0]) - for w in good_nodes: - g.set_row(w, leftrow+2) - new_right.append(unspider_by_row(g, w)) - - left.sort(key=g.qubit) - qs = [g.qubit(v) for v in left] - m = bi_adj(g, new_right, left) - target = column_optimal_swap(m) - for i, j in target.items(): - g.set_qubit(new_right[i],qs[j]) - new_right.sort(key=g.qubit) - m = bi_adj(g, new_right, left) - gates = m.to_cnots(optimize=True) - for cnot in gates: - cnot.target = qs[cnot.target] - cnot.control = qs[cnot.control] - for i in range(q): - for j in range(q): - if g.connected(left[i],new_right[j]): - if i != j: - g.remove_edge(g.edge(left[i],new_right[j])) - elif i == j: - g.add_edge((left[i],new_right[j]), EdgeType.HADAMARD) - if not quiet: print("Greedy extract with {:d} nodes and {:d} CNOTs".format(len(good_nodes),len(gates))) - return gates, True - - - -def handle_phase_gadget(g, left, neigh, special_nodes, quiet=True): - """Tries to find a cut of the graph at the given leftrow so that a single phase-gadget can be extracted. - Returns a list of extracted gates and modifies the graph g in place. Used by :func:`streaming_extract`""" - q = len(left) - qs = g.qubits() # We are assuming this thing automatically updates - rs = g.rows() - leftrow = rs[left[0]] - gadgets = neigh.intersection(special_nodes) # These are the phase gadgets that are attached to the left row - if len(gadgets) == 0: raise ValueError("No phase gadget connected to this row") - all_verts = neigh.union(left).union(special_nodes.values()) - right = list(neigh) - options = [] - for gadget in gadgets: - if all(w in all_verts for w in g.neighbours(gadget)): - options.append(gadget) - #print(options) - for o in options: # We move the candidates gadgets to the end of the list - right.remove(o) - right.append(o) - #print(right) - m = bi_adj(g, right, left+options) - r = reduce_bottom_rows(m, q) - gadget = options[r-len(left)] # This is a gadget that works - right.remove(gadget) - - g.set_row(gadget,leftrow+1) - g.set_row(special_nodes[gadget],leftrow+1) - - # Take care nothing is connected directly to an output - for i in range(len(right)): - w = right[i] - if w in g.outputs: - w2 = g.add_vertex(VertexType.Z, qs[w], rs[w]-1) - n = list(g.neighbours(w))[0] # Outputs should have unique neighbours - e = g.edge(n,w) - et = g.edge_type(e) - g.remove_edge(e) - g.add_edge((n,w2),EdgeType.HADAMARD) - g.add_edge((w2,w),toggle_edge(et)) - right[i] = w2 - - if len(right) == q: - if not quiet: print("No cutting necessary") - for w in right: - g.set_row(w, leftrow+2) - else: - right = cut_edges(g, left+[gadget], right) - # We have now prepared the stage to do the extraction of the phase gadget - - phase = g.phase(special_nodes[gadget]) - phase = -1*phase if g.phase(gadget) != 0 else phase - left.sort(key=g.qubit) - qv = [qs[v] for v in left] - m = bi_adj(g, right, left) - target = column_optimal_swap(m) - for i, j in target.items(): - g.set_qubit(right[i],qv[j]) - right.sort(key=g.qubit) - - m = bi_adj(g, right, left) - if m.rank() != q: - raise Exception("Rank in phase gadget reduction too low.") - operations = Circuit(q) - operations.row_add = lambda r1,r2: operations.gates.append((r1,r2)) - m.gauss(full_reduce=True,x=operations) - gates = [CNOT(qv[r2],qv[r1]) for r1,r2 in operations.gates] - m = bi_adj(g, right+[gadget], left) - for r1,r2 in operations.gates: - m.row_add(r1,r2) - connectivity_from_biadj(g, m, right+[gadget], left) - - # Now the connections from the left to the right are like the identity - # with some wires coming to the gadget from the left and from the right - gadget_left = [v for v in left if g.connected(gadget, v)] - gadget_right = [w for w in right if g.connected(gadget, w)] - targets = [qs[v] for v in gadget_left] - # We bring as many connections on the right to the left - for i in reversed(range(len(gadget_right))): # The following checks if every phase connected node is on the right - w = gadget_right[i] - v = next(v for v in left if g.connected(w,v)) - g.set_edge_type((v,w),EdgeType.SIMPLE) - g.set_qubit(w, qs[v]) - if qs[w] not in targets: - gates.append(HAD(qs[w])) - gadget_right.pop(i) - targets.append(qs[w]) - gadget_left.append(v) - else: - g.set_row(w, leftrow+1) - - if not gadget_right: #Only connected on leftside so we are done - if not quiet: print("Simple phase gadget") - gate = ParityPhase(phase, *targets) - g.remove_vertices([special_nodes[gadget],gadget]) - gates.append(gate) - return gates, leftrow - - if not quiet: print("Complicated phase gadget") # targets on left and right, so need to do more - if len(gadget_right) % 2 != 0 or len(gadget_left) == 1: - raise Exception("Gadget seems non-unitary") - - #Now we can finally extract the phase gadget - rtargets = [] - for w in gadget_right: - t = qs[w] - rtargets.append(t) - gates.extend([HAD(t),ZPhase(t,Fraction(-1,2)),HAD(t)]) - if len(gadget_right)%4 != 0: # This is either 2 or 0 - phase = (-phase)%2 - gates.append(ParityPhase(phase, *targets)) - for t in rtargets: - gates.extend([HAD(t),ZPhase(t, Fraction(1,2))]) - for v in left: - if qs[v] not in rtargets: - g.set_row(v, leftrow+1) - - g.remove_vertices([special_nodes[gadget],gadget]) - return gates, leftrow+1 - -def reduce_bottom_rows(m, qubits): - """Using just row_add's from the first qubit rows in m, tries to find a row that can be - completely zero'd out. Returns the rownumber of this row when successful.""" - cols = m.cols() - leading_one = {} - adds = [] - for r in range(qubits): - while True: - i = next(i for i in range(cols) if m.data[r][i]) - if i in leading_one: - m.row_add(leading_one[i],r) - adds.append((leading_one[i],r)) - else: - leading_one[i] = r - break - for r in range(qubits, m.rows()): - while True: - if not any(m.data[r]): - return r - i = next(i for i in range(cols) if m.data[r][i]) - if i not in leading_one: break - m.row_add(leading_one[i], r) - adds.append((leading_one[i],r)) - raise ValueError("Did not find any completely reducable row") - -def find_ancilla_qubits(g, left, right, gadgets, maxq, quiet=True): - leftrow = g.row(left[0]) - nodes = list(right.difference(gadgets)) - right = list(right) - for w in nodes: - right.remove(w) - right.append(w) - m = bi_adj(g, right, left) - m.gauss(full_reduce=True) - candidates = [] - ancilla_count = 100000 - for row in m.data: - if not any(row[:-len(nodes)]): - verts = [right[i] for i,a in enumerate(row) if a] - if len(verts) < ancilla_count: - candidates = [verts] - ancilla_count = len(verts) - elif len(verts) == ancilla_count: - candidates.append(verts) - if not candidates: - raise ValueError("No valid ancilla vertices found") - if not quiet: print("Adding {:d} ancillas".format(ancilla_count-1)) - if len(candidates) == 1: - ancillas = candidates[0][:-1] - else: - all_candidates = set() - for cand in candidates: all_candidates.update(cand) - best_set = None - best_count = 100000 - for poss in itertools.combinations(all_candidates, ancilla_count-1): - s = sum(1 for cand in candidates if all(v in cand for v in poss)) - if s < best_count: - best_count = s - best_set = poss - ancillas = best_set - - gates = [] - for i, v in enumerate(ancillas): - g.set_row(v, leftrow) - g.set_qubit(v, maxq+i) - w = g.add_vertex(VertexType.Z, maxq+i, leftrow-1) - g.add_edge((v,w),EdgeType.SIMPLE) - gates.append(InitAncilla(maxq+i)) - #raise Exception - return gates, maxq+len(ancillas) - - - - +def streaming_extract(g, optimize_czs=True, optimize_cnots=2, quiet=True): + print("This function is deprecated. Call extract_circuit() instead.") + return extract_circuit(g, optimize_czs, optimize_cnots, quiet) def permutation_as_swaps(perm): """Returns a series of swaps the realises the given permutation. @@ -799,9 +241,11 @@ def filter_duplicate_cnots(cnots): c = basic_optimization(c,do_swaps=False) return c.gates -def modified_extract(g, optimize_czs=True, optimize_cnots=2, quiet=True): +def extract_circuit(g, optimize_czs=True, optimize_cnots=2, quiet=True): """Given a graph put into semi-normal form by :func:`~pyzx.simplify.full_reduce`, it extracts its equivalent set of gates into an instance of :class:`~pyzx.circuit.Circuit`. + This function implements a more optimized version of the algorithm described in + `There and back again: A circuit extraction tale `_ Args: g: The ZX-diagram graph to be extracted into a Circuit. diff --git a/pyzx/scripts/circ2circ.py b/pyzx/scripts/circ2circ.py index bd3807a2..e938cca7 100644 --- a/pyzx/scripts/circ2circ.py +++ b/pyzx/scripts/circ2circ.py @@ -82,7 +82,7 @@ def main(args): if options.simp == 'cliff': simplify.clifford_simp(g,quiet=(not options.verbose)) if options.verbose: print("Extracting circuit...") - c2 = extract.streaming_extract(g) + c2 = extract.extract_circuit(g) if options.verbose: print("Optimizing...") if options.phasepoly: c3 = optimize.full_optimize(c2.to_basic_gates()) diff --git a/tests/long_test.py b/tests/long_test.py index 286e12ff..393a143f 100644 --- a/tests/long_test.py +++ b/tests/long_test.py @@ -24,7 +24,7 @@ from pyzx.tensor import compare_tensors from pyzx.generate import cliffordT from pyzx.simplify import * -from pyzx.extract import * +from pyzx.extract import extract_circuit from pyzx.circuit import Circuit from pyzx.optimize import * @@ -50,8 +50,8 @@ def do_tests(qubits, depth, iterations, test_clifford_graph=True): steps.append("clifford_simp") if test_clifford_graph: compare(t, g) - c = streaming_extract(g) - steps.append("streaming_extract") + c = extract_circuit(g) + steps.append("extract_circuit") compare(t, c, False) c = c.to_basic_gates() @@ -68,18 +68,10 @@ def do_tests(qubits, depth, iterations, test_clifford_graph=True): steps.append("full_reduce") if test_clifford_graph: compare(t, g) - c = modified_extract(g) - steps.append("modified_extract") + c = extract_circuit(g) + steps.append("extract_circuit") compare(t,c,False) - steps = [] - g = circ.copy() - full_reduce(g, quiet=True) - steps.append("full_reduce") - c = streaming_extract(g).to_basic_gates() - steps.append("streaming_extract") - compare(t, c, False) - steps = [] g = circ.copy() #to_gh(g) diff --git a/tests/test_circuit.py b/tests/test_circuit.py index 905178ff..6119f291 100644 --- a/tests/test_circuit.py +++ b/tests/test_circuit.py @@ -30,7 +30,7 @@ from pyzx.generate import cliffordT, cliffords from pyzx.simplify import clifford_simp -from pyzx.extract import streaming_extract +from pyzx.extract import extract_circuit from pyzx.circuit import Circuit SEED = 1337 @@ -92,7 +92,7 @@ def test_circuit_extract_preserves_semantics(self): g = cliffordT(5, 70, 0.15) t = g.to_tensor(False) clifford_simp(g, quiet=True) - c = streaming_extract(g) + c = extract_circuit(g) t2 = c.to_tensor(False) self.assertTrue(compare_tensors(t,t2,False)) diff --git a/tests/test_extract.py b/tests/test_extract.py index e61b2970..60a46754 100644 --- a/tests/test_extract.py +++ b/tests/test_extract.py @@ -32,7 +32,7 @@ from pyzx.circuit.gates import CNOT from pyzx.generate import cliffordT, cliffords from pyzx.simplify import clifford_simp -from pyzx.extract import streaming_extract, modified_extract +from pyzx.extract import extract_circuit SEED = 1337 @@ -40,55 +40,14 @@ @unittest.skipUnless(np, "numpy needs to be installed for this to run") class TestExtract(unittest.TestCase): - # def test_clifford_extract(self): - # random.seed(SEED) - # tests = 0 - # tries = 0 - # while True: - # tries += 1 - # circ = cliffords(5,70) - # clifford_simp(circ,quiet=True) - # circ.normalise() - # if circ.depth()>3: continue # It is not in normal form, so skip this one - # tests += 1 - # with self.subTest(test=tests,tries=tries): - # t = tensorfy(circ) - # clifford_extract(circ,1,2) - # t2 = tensorfy(circ) - # self.assertTrue(compare_tensors(t,t2)) - # if tests>5: break - - # def test_greedy_cut_extract(self): - # random.seed(SEED) - # for i in range(5): - # circ = cliffordT(4,50,0.1) - # clifford_simp(circ,quiet=True) - # circ.normalise() - # with self.subTest(i=i): - # t = tensorfy(circ) - # greedy_cut_extract(circ) - # t2 = tensorfy(circ) - # self.assertTrue(compare_tensors(t,t2)) - - # def test_circuit_extract(self): - # random.seed(SEED) - # for i in range(5): - # circ = cliffordT(4,50,0.1) - # clifford_simp(circ,quiet=True) - # with self.subTest(i=i): - # t = tensorfy(circ) - # circuit_extract(circ) - # t2 = tensorfy(circ) - # self.assertTrue(compare_tensors(t,t2)) - - def test_streaming_extract(self): + def test_extract_circuit(self): random.seed(SEED) for i in range(5): circ = cliffordT(4,50,0.1) t = tensorfy(circ,False) clifford_simp(circ,quiet=True) with self.subTest(i=i): - c = streaming_extract(circ) + c = extract_circuit(circ) t2 = c.to_tensor(False) self.assertTrue(compare_tensors(t,t2,False)) @@ -101,7 +60,7 @@ def test_cz_optimise_extract(self): g = c.to_graph() clifford_simp(g,quiet=True) - c2 = modified_extract(g) + c2 = extract_circuit(g) cnot_count = 0 for gate in c2.gates: if isinstance(gate, CNOT):