ExamplesΒΆ


The first example is a feed forward network

import numpy as np
from viznet import connecta2a, node_sequence, NodeBrush, EdgeBrush, DynamicShow


def draw_feed_forward(ax, num_node_list):
    '''
    draw a feed forward neural network.

    Args:
        num_node_list (list<int>): number of nodes in each layer.
    '''
    num_hidden_layer = len(num_node_list) - 2
    token_list = ['\sigma^z'] + \
        ['y^{(%s)}' % (i + 1) for i in range(num_hidden_layer)] + ['\psi']
    kind_list = ['nn.input'] + ['nn.hidden'] * num_hidden_layer + ['nn.output']
    radius_list = [0.3] + [0.2] * num_hidden_layer + [0.3]
    y_list = 1.5 * np.arange(len(num_node_list))

    seq_list = []
    for n, kind, radius, y in zip(num_node_list, kind_list, radius_list, y_list):
        b = NodeBrush(kind, ax)
        seq_list.append(node_sequence(b, n, center=(0, y)))

    eb = EdgeBrush('-->', ax)
    for st, et in zip(seq_list[:-1], seq_list[1:]):
        connecta2a(st, et, eb)


def real_bp():
    with DynamicShow((6, 6), '_feed_forward.png') as d:
        draw_feed_forward(d.ax, num_node_list=[5, 4, 1])


if __name__ == '__main__':
    real_bp()
$ python apps/nn/feed_foward.py

The output is

_images/feed_forward_example.png

The second example is tensor network TEBD algorithm, it is also a good example to learn the grid system.

from viznet import theme, EdgeBrush, DynamicShow, Grid, NodeBrush


def tebd():
    # define a grid with grid space dx = 1, and dy = 1.
    grid = Grid((1, 1))

    # define a set of brushes.
    # NodeBrush can place a node at some location, like `node_brush >> (x, y)`,
    # and it will return a Node instance.
    # EdgeBrush can connect two Nodes (or Pin as a special Node),
    # like `edge_brush >> node_a, node_b`, and will return an Edge instance.
    size = 'normal'
    mps = NodeBrush('tn.mps', size=size)
    # invisible node can be used as a placeholder
    invisible_mps = NodeBrush('invisible', size=size)
    # define a two site mpo, which will occupy 1 column, 0 rows.
    mpo21 = NodeBrush('tn.mpo', size=size)
    edge = EdgeBrush('-', lw=2.)

    with DynamicShow((6, 4), filename='_tebd.png') as ds:
        # add a sequence of mps nodes, a store them in a list for future use.
        mps_list = []
        for i in range(8):
            mps_list.append(mps >> grid[i, 0])
            mps_list[-1].text(r'$\sigma_%d$' % i, position='bottom')
        mps_list.append(invisible_mps >> grid[i + 1, 0])

        # add mpo and connect nodes
        for layer in range(4):
            # set brush color, it will overide theme color!
            # You can set brush color to None to restore theme color.
            mpo21.color = theme.RED if layer % 2 == 0 else theme.GREEN
            mpo_list = []
            start = layer % 2
            for i, (mps_l, mps_r) in enumerate(zip(mps_list[start::2],
                                                   mps_list[start + 1::2])):
                # place an two site mpo slightly above the center of two mps nodes
                y = mps_l.position[1]+layer + 1
                mpo_list.append(mpo21 >> grid[mps_l.position[0]:mps_r.position[0], y:y])
                if layer == 0:
                    # if this is the first mpo layer, connect mps and newly added mpo.
                    pin_l = mps_l
                    pin_r = mps_r
                else:
                    # otherwise, place a pin at the top surface of previous mpo,
                    # we also require it horizontally aligned to some `mps_l` object.
                    # pin is a special node, which is zero sized,
                    # we can use it to connect nodes, add texts.
                    # if you're about to place some pin at `left` or
                    # `right` surface of a node,
                    # align is then intepreted as vertial align.
                    pin_l = mpo_list_pre[i].pin('top', align=mps_l)
                    pin_r = mpo_list_pre[i].pin('top', align=mps_r)
                if layer < 2:
                    edge >> (mps_l, mps_r)
                edge >> (pin_l, mpo_list[-1].pin('bottom', align=mps_l))
                edge >> (pin_r, mpo_list[-1].pin('bottom', align=mps_r))
            mpo_list_pre = mpo_list


if __name__ == '__main__':
    tebd()
$ python apps/tn/tebd.py

The output is

_images/tebd.png

The third example is a quantum circuit

import matplotlib.pyplot as plt
from viznet import DynamicShow, QuantumCircuit
from viznet import parsecircuit as _


def ghz4():
    '''4 bit GHZ circuit, applicable on ibmqx4 circuit.'''
    num_bit = 4
    with DynamicShow((5, 3), '_exact_ghz4_circuit.png') as ds:
        handler = QuantumCircuit(num_bit=4, y0=2.)
        handler.x += 0.5
        handler.gate(_.GATE, 0, 'X')
        for i in range(1, num_bit):
            handler.gate(_.GATE, i, 'H')
        handler.x += 1
        handler.gate((_.C, _.NOT), (1, 0))
        handler.gate((_.C, _.NOT), (3, 2))
        handler.x += 0.7
        handler.gate((_.C, _.NOT), (2, 0))
        handler.x += 0.7
        handler.gate((_.C, _.NOT), (3, 2))
        handler.x += 1
        for i in range(num_bit):
            handler.gate(_.GATE, i, 'H')
        handler.x += 1
        for i in range(num_bit):
            handler.gate(_.MEASURE, i)
        handler.edge.style = '='
        handler.x += 0.8
        for i in range(num_bit):
            handler.gate(_.END, i)

        # text |0>s
        for i in range(num_bit):
            plt.text(*handler.get_position(i, x=-0.5), r'$\left\vert0\right\rangle_{Q_%d}$' %
                     i, va='center', ha='center', fontsize=18)


if __name__ == '__main__':
    ghz4()
$ python apps/qc/ghz.py

The output is

_images/ghz4.png

Here, we used the QuantumCircuit instance handler to help us build the circuit. gate method of handler take brush(es) as first argument and line(lines) as second argument. handler.x decide the x axis of this gate.