Skip to content

seeqc/sfqlib

 
 

Repository files navigation

./demo.png

Installation

The code is developed in python2, but python3 should not be a problem.

pip install sfqlib

For the latest version, install from the wheels in dist/. Documentation can be found at readthedocs.org.

Create a Qubit

When a qubit is created, it starts at |0> state. However, all 6 cardinal states on the block sphere are tracked. There are two types of basic qubit.

  • Sfq3LevelQubit: A qubit that includes the leakage level.
  • Sfq2LevelQubit: An ideal two level qubit.

Each qubit is defined by its

  • Qubit frequency (both w01 and w12)
  • Clock frequency.
  • Rotation induced by a single SFQ pulse.
  • Target rotation, against which we define the infidelity.

For example, to create a 3 level qubit.

qubit = Sfq3LevelQubit(d_theta=pi/200, w_clock=2*pi*5e9,
      w_qubit=(2*pi*5.0e9, 2*pi*9.8e9), theta=pi/2)

Qubit Evolution.

Evolve a qubit

We can do three basic things on a qubit.

  • precess for one clock period.
    qubit.precess()
        
  • Apply a SFQ pulse and precess for one clock period. It is pulse_and_precess rather than pulse because
    • Applying two pulses consecutively is not possible experimentally.
    • It simplifies programming.
    qubit.pulse_and_precess()
        
  • Measure the fidelity. The fidelity is averaged over the 6 states.
    qubit.measure_fidelity()
        

    In case of three level qubits, you can optionally ignore the indelity due to leakage level.

    qubit.measure_fidelity(ignore_leakage=True)
        

    Suppose that we created a qubit

More usage

You can apply arbitrary pulse sequences by interleaving precess and pulse_and_precess, but there are a few helper functions for doing that.

Resonance

You can apply a resonance requence that achieves that target rotation by

qubit.resonance()

Pulse pattern

A sequence can be specified as a bit string. Each bit corresponds to a clock edge, where

  • 1 means applying a SFQ pulse at the clock edge.
  • 0 means not applying a SFQ pulse at the clock edge.

For example, if one wants to apply pulses at the 4th and 6th clock edge.

pattern = [0, 0, 0, 1, 0, 1]
qubit.pulse_pattern(pattern)

Pulse sequence

Create a pattern

To avoid the tedium of typing up patterns, we can specify a pattern as a decimal number. a class sfqsequence is provided for this purpose. For example, one can create the bit pattern [1, 0, 0, 0] like the following.

sequence = sfqsequence(8, 4).binary

This is convinent for enumerating large number of sequences.

# All sequence that is 10 bits long.
[sfqsequence(i, 10) for i in range(pow(2, 10))]

Evolve the qubit

To apply a sequence to a qubit.

qubit.pulse_pattern(sequence.binary):

As another example, to try all possible sequences of n bits long.

def search_sequences_of_length(self, n):
    def try_sequence(sequence_num):
        qubit = self.Sfq3LevelQubit(
            d_theta=self.d_theta_n/n, w_clock=self.w_clock,
            w_qubit=(2*pi*5.0e9, 2*pi*9.8e9), theta=pi/2)
        sequence = SfqSequence(sequence_num, n)
        qubit.pulse_pattern(sequence.binary)
        sequence.fidelity = qubit.measure_fidelity()
        return sequence
    all_seq_of_length_n = [try_sequence(sequence_num)
                          for sequence_num in range(pow(2, n))]
    return all_seq_of_length_n

Fancy Qubits

The qubit implementation discussed above runs at the speed of C++ when numpy uses MKL. To maintain that speed, operations that harm performance are separated into FancyQubits. Currently, there are two main features in FancyQubits.

  • Euler angles.
  • Visual Qubit.

Create a Fancy Qubit

To allow users to manipulate the visualization, the qubit will be visualized on a axis provided by the user.

Sfq2LevelFancyQubit

For 2 level qubit, one axis is required.

qubit = Sfq2LevelFancyQubit(axis, d_theta=pi/200, w_clock=2*pi*40e9,
                            w_qubit=(2*pi*5.0e9, 2*pi*9.8e9), theta=pi/2)

Sfq3LevelFancyQubit

For 3 level qubit, to plot in both the 0-1 subspace and the 1-2 subspace, 2 axes are required.

qubit = Sfq3LevelFancyQubit((axis_01, axis_12), d_theta=pi/200, w_clock=2*pi*40e9,
                            w_qubit=(2*pi*5.0e9, 2*pi*9.8e9), theta=pi/2)

Euler angles.

Fancy qubit records the Euler angles of the rotation at each step. For mathematical details, see the document `euler.pdf`.

Visual Qubit

BEFORE evolving the qubit, use the function `set_projection_source` to specify which cardinal states you would like visualize. The states are specified as the following.

  • ‘G’: Ground (+z)
  • ‘E’: Excited (-z)
  • ‘P’: (+x)
  • ‘P_I’: (+y)
  • ‘M’: (-x)
  • ‘M_I’: (-y)

Usage

First we initiate some axes.

fig = plt.figure(figsize=(10, 10))
axis_01 = fig.add_subplot(2, 2, 1, projection='3d', label='0-1 subspace')
axis_12 = fig.add_subplot(2, 2, 2, projection='3d', label='1-2 subspace')
axis_alpha = fig.add_subplot(2, 2, 3)
axis_beta = fig.add_subplot(2, 2, 4)

Then we create a qubit.

qubit = Sfq3LevelFancyQubit((axis_01, axis_12), d_theta=pi/200, w_clock=2*pi*40e9,
                            w_qubit=(2*pi*5.0e9, 2*pi*9.8e9), theta=pi/2)

Specify the cardinal states to visualize. In this case, we want all states.

qubit.set_plot_kets(['G', 'E', 'P', 'M_I', 'P_I', 'M'])

Evolve the qubit. Note that this is a resonant sequence.

for i in range(30):
    qubit.pulse_and_precess()
    for j in range(7):
        qubit.precess()

Plot the Euler angles.

axis_alpha.plot(qubit.alpha_list, label=r'$\alpha$', color='r')
axis_beta.plot(qubit.beta_list, label=r'$\beta$', color='b')

Show the plot.

axis_alpha.legend()
axis_beta.legend()
plt.show()

./result.png

Notes

  • If you are using Jupyter notebook or IPython REPL, the qubit visualization supports interactive plotting. Examples are shown in folder ./notebooks.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 87.7%
  • Jupyter Notebook 9.1%
  • Emacs Lisp 3.2%