{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Visualizing the patterns and flows\n\n:class:`~graphix.visualization.GraphVisualizer` tool offers a wide selection of \nvisualization methods for inspecting the causal structure of the graph associated \nwith the pattern, graph or the (generalized-)flow.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Causal flow\nFirst, let us inspect the flow and gflow associated with the resource graph of a pattern.\nsimply call :meth:`~graphix.pattern.Pattern.draw_graph` method.\nBelow we list the meaning of the node boundary and face colors.\n\n- Nodes with red boundaries are the *input nodes* where the computation starts.\n- Nodes with gray color is the *output nodes* where the final state end up in.\n- Nodes with blue color is the nodes that are measured in *Pauli basis*, one of *X*, *Y* or *Z* computational bases.\n- Nodes in white are the ones measured in *non-Pauli basis*.\n\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import numpy as np\nfrom graphix import Circuit\n\ncircuit = Circuit(3)\ncircuit.cnot(0, 1)\ncircuit.cnot(2, 1)\ncircuit.rx(0, np.pi / 3)\ncircuit.x(2)\ncircuit.cnot(2, 1)\npattern = circuit.transpile().pattern\n# note that this visualization is not always consistent with the correction set of pattern,\n# since we find the correction sets with flow-finding algorithms.\npattern.draw_graph(flow_from_pattern=False, show_measurement_planes=True)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "next, show the gflow:\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "pattern.perform_pauli_measurements(leave_input=True)\npattern.draw_graph(flow_from_pattern=False, show_measurement_planes=True, node_distance=(1, 0.6))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Correction set ('xflow' and 'zflow' of pattern)\nnext let us visualize the X and Z correction set in the pattern by :code:`flow_from_pattern=False` statement.\n\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# node_distance argument specifies the scale of the node arrangement in x and y directions.\npattern.draw_graph(flow_from_pattern=True, show_measurement_planes=True, node_distance=(0.7, 0.6))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Instead of the measurement planes, we can show the local Clifford of the resource graph.\nsee `clifford.py` for the details of the indices of each single-qubit Clifford operators.\n6 is the Hadamard and 8 is the $\\sqrt{iY}$ operator.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "pattern.draw_graph(flow_from_pattern=True, show_local_clifford=True, node_distance=(0.7, 0.6))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Visualize based on the graph\nThe visualizer also works without the pattern. Simply supply the\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import networkx as nx\n\nfrom graphix.visualization import GraphVisualizer\n\n# graph with gflow but no flow\nnodes = [1, 2, 3, 4, 5, 6]\nedges = [(1, 4), (1, 6), (2, 4), (2, 5), (2, 6), (3, 5), (3, 6)]\ninputs = {1, 2, 3}\noutputs = {4, 5, 6}\ngraph = nx.Graph()\ngraph.add_nodes_from(nodes)\ngraph.add_edges_from(edges)\nmeas_planes = {1: \"XY\", 2: \"XY\", 3: \"XY\"}\nvis = GraphVisualizer(graph, inputs, outputs, meas_plane=meas_planes)\nvis.visualize(show_measurement_planes=True)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "# graph with extended gflow but no flow\nnodes = [0, 1, 2, 3, 4, 5]\nedges = [(0, 1), (0, 2), (0, 4), (1, 5), (2, 4), (2, 5), (3, 5)]\ninputs = {0, 1}\noutputs = {4, 5}\ngraph = nx.Graph()\ngraph.add_nodes_from(nodes)\ngraph.add_edges_from(edges)\nmeas_planes = {0: \"XY\", 1: \"XY\", 2: \"ZX\", 3: \"YZ\"}\nvis = GraphVisualizer(graph, inputs, outputs, meas_plane=meas_planes)\nvis.visualize(show_measurement_planes=True)"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.10.13"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}