Qulacs Documentation

Qulacs is a fast quantum circuit simulator for simulating large, noisy, or parametric quantum circuits. Implemented in C/C++ and with Python interface, Qulacs achieved both high speed circuit simulation and high usability.

Qulacs was developed in Prof. Fujii’sgroup. Maintained and developing new features by QunaSys.

Get Started

pip install qulacs

Detailed instructions about installation in Installation. Having trouble starting? see FAQ. For basic usage of Qulacs in Python and C++, see Usage.

About Qulacs

Qulacs is a Python/C++ library for fast simulation of large, noisy, or parametric quantum circuits. Qulacs is developed at QunaSys, Osaka University, NTT and Fujitsu.

Qulacs is licensed under the MIT license.

Features

  • Fast quantum circuit simulation with parallelized C/C++ backend

  • Noisy quantum gate for simulation of NISQ devices

  • Parametric quantum gates for variational methods

  • Circuit compression for fast simulation

  • GPU support for fast simulation

  • Many utility functions for research

Performance

The time for simulating random quantum circuits is compared with several quantum circuit simulators in November 2020.

See the benchmark repository and Section VI and VII of our paper for the detail of this benchmark.

Note that the plots with names ending with “opt” and “heavy opt” perform circuit optimization for fast simulation, where the time for optimization is included in the execution time.

Single-thread benchmark

single thread benchmark

Multi-thread benchmark

multi thread benchmark

GPU benchmark

multi thread benchmark

Requirement

  • C++ compiler (gcc or VisualStudio)

    • gcc/g++ >= 7.0.0 (checked in Linux, MacOS, cygwin, MinGW, and WSL)

    • Microsoft VisualStudio C++ 2015 or 2017

  • Python 2.7 or 3.x

  • CMake >= 3.0

  • Git

  • (option) CUDA >= 8.0

  • (option) AVX2 support

If your system supports AVX2 instructions, SIMD optimization is automatically enabled. If you want to enable GPU simulator, install qulacs through qulacs-gpu package or build from source. Note that qulacs-gpu includes a CPU simulator. You don’t need to install both.

If you encounter some troubles, see FAQ.

How to cite

Please cite this arXiv paper: Qulacs: a fast and versatile quantum circuit simulator for research purpose.

Installation

Quick Install

pip install qulacs

If your CPU is older than Intel Haswell architecture, the binary installed with the above command does not work. In this case, please install Qulacs with the following command. Even if your CPU is newer than Haswell, Qulacs installed with the below command shows better performance but takes a longer time. See “Install Python library from source” section for detail.

pip install git+https://github.com/qulacs/qulacs.git

If you have NVIDIA GPU and CUDA is installed, GPU-version can be installed with the following command:

pip install qulacs-gpu

Install Python library from source

To install Qulacs optimized for your system, we recommend the following install procedure for faster simulation of quantum circuits, while this requires a compiler and takes time for installation. In addition, you can enable or disable optimization features such as SIMD optimization, OpenMP parallelization, and GPU support.

A binary that is installed via pip command is optimized for Haswell architecture. Thus, Qulacs installed via pip command does not work with a CPU older than Haswell. If your CPU is newer than Haswell, Qualcs built from source shows the better performance.

Requirements
  • C++ compiler (gcc or VisualStudio)

    • gcc/g++ >= 7.0.0 (checked in Linux, MacOS, cygwin, MinGW, and WSL)

    • Microsoft VisualStudio C++ 2015 or 2017

  • Boost >= 1.71.0 (Minimum version tested in CI)

  • Python 2.7 or 3.x

  • CMake >= 3.0

  • Git

  • (option) CUDA >= 8.0

  • (option) AVX2 support

If your system supports AVX2 instructions, SIMD optimization is automatically enabled. If you want to enable GPU simulator, install qulacs through qulacs-gpu package or build from source. Note that qulacs-gpu includes a CPU simulator. You don’t need to install both.

Qulacs is tested on the following systems.

  • Ubuntu 20.04

  • macOS Big Sur 11

  • Windows Server 2019

If you encounter some troubles, see FAQ.

How to install

Install with default options (Multi-thread without GPU):

pip install .

If AVX2 instructions are not supported, SIMD optimization is automatically disabled.

Install with GPU support (CUDA is required):

USE_GPU=Yes pip install .

Install single-thread Qulacs:

USE_OMP=No pip install .

The number of threads used in Qulacs installed with default options can be controlled via the environment variable OMP_NUM_THREADS or QULACS_NUM_THREADS. While OMP_NUM_THREADS affects the parallelization of other libraries, QULACS_NUM_THREADS controls only the parallelization of QULACS. Or, if you want to force only Qulacs to use a single thread, You can install single-thread Qulacs with the above command.

For development purpose, optional dependencies can be installed as follows.

# Install development tools
pip install .[dev]
# Install dependencies for document generation
pip install .[doc]

Uninstall Qulacs:

pip uninstall qulacs
Build C++ and Python library
Build with GCC

Static libraries of Qulacs can be built with the following command:

git clone https://github.com/qulacs/qulacs.git
cd qulacs
./script/build_gcc.sh

To build shared libraries, execute make shared at ./qulacs/build folder. When you want to build with GPU, use build_gcc_with_gpu.sh instead of build_gcc.sh.

When you want to build with GPU, use build_gcc_with_gpu.sh.

Build with MSVC

Static libraries of Qulacs can be built with the following command:

git clone https://github.com/qulacs/qulacs.git
cd qulacs
script/build_msvc_2017.bat

When you want to build with GPU, use build_msvc_2017_with_gpu.bat. If you use MSVC with other versions, use build_msvc_2015.bat or edit the generator name in build_msvc_2017.bat.

FAQ

Trouble-shootings

Compile error in C/C++
When I try to compile the C++ library, I get compile errors.

Codes might not be compiled with gcc or g++ version>=7.0.0. Please check codes are compiled with gcc and g++ and its version is greater or equal to 7.0.0.

For macOS Users: The default backend of gcc or g++ command is clang, which is not supported in Qulacs.

When I compile Qulacs with MinGW, the compiler says header files such as crypt.h or sys/select.h was not found. When objects are linked, the linker says library -lintl was not found.

This may occur when you try to build the 32bit Python library withthe 64bit compiler, or when you try to build the 64bit Python library with the 32bit compiler. If you compile the C++ library with 32bit/64bit, the Python library must be 32bit/64bit, respectively.

Error in Python library
I have many versions of Python, and I want to build Qulacs for a specific one.

Qulacs is built using the default Python. Please set the version of Python you want to use with pyenv or conda as the default. Then build Qulacs.

You can also specify a Python binary when building with CMake by adding -D PYTHON_EXECUTABLE:FILEPATH=/usr/bin/pythonx.x.

When I import the library, Python says there is no init function.

If you use Qulacs from Python and call functions directly using dll/pyd, do not change the name of the Python library. If you have changed the dll/pyd name of the Python library, you will see this error.

If you import the dll/pyd built with a different version of Python, you may see this error.

When I import the library, I get a Segmentation fault error.
Why does Python immediately exit when I import the library?
Why does Python miss functions that start with Py_?
Though there exist dll files, Python says there is no dll/pyd.

If you import dll/pyd built with a different version of Python, you will see these errors. Error messages depend on the version of Python.

Usage

See the following documents for more detail.

C++ Libraries

Add ./<qulacs_path>/include/ to include path, and ./<qulacs_path>/lib/ to library path.

Example of C++ code:

#include <iostream>
#include <cppsim/state.hpp>
#include <cppsim/circuit.hpp>
#include <cppsim/observable.hpp>

int main(){
    QuantumState state(3);
    state.set_Haar_random_state();

    QuantumCircuit circuit(3);
    circuit.add_X_gate(0);
    auto merged_gate = gate::merge(gate::CNOT(0,1),gate::Y(1));
    circuit.add_gate(merged_gate);
    circuit.add_RX_gate(1,0.5);
    circuit.update_quantum_state(&state);

    Observable observable(3);
    observable.add_operator(2.0, "X 2 Y 1 Z 0");
    observable.add_operator(-3.0, "Z 2");
    auto value = observable.get_expectation_value(&state);
    std::cout << value << std::endl;
    return 0;
}
GCC

You can build your codes with the following gcc commands:

g++ -O2 -I ./<qulacs_path>/include -L ./<qulacs_path>/lib <your_code>.cpp -lvqcsim_static -lcppsim_static -lcsim_static -fopenmp

If you want to run your codes with GPU, include cppsim/state_gpu.hpp and use QuantumStateGpu instead of QuantumState and build with the following command:

nvcc -O2 -I ./<qulacs_path>/include -L ./<qulacs_path>/lib <your_code>.cu -lvqcsim_static -lcppsim_static -lcsim_static -lgpusim_static -D _USE_GPU -lcublas -Xcompiler -fopenmp
MSVC

Your C++ codes can be built with Qulacs with the following process:

  1. Create an empty project.

  2. Select x64 as an active solution platform.

  3. Right Click your project name in Solution Explorer, and select Properties.

  4. At VC++ Directories section, add the full path to ./qulacs/include to Include Directories

  5. At VC++ Directories section, add the full path to ./qulacs/lib to Library Directories

  6. At C/C++ -> Code Generation section, change Runtime library to Multi-threaded (/MT).

  7. At Linker -> Input section, add vqcsim_static.lib;cppsim_static.lib;csim_static.lib; to Additional Dependencies.

Python Libraries

You can use features by simply importing qulacs.

Example of Python code:

from qulacs import Observable, QuantumCircuit, QuantumState
from qulacs.gate import Y,CNOT,merge

state = QuantumState(3)
state.set_Haar_random_state()

circuit = QuantumCircuit(3)
circuit.add_X_gate(0)
merged_gate = merge(CNOT(0,1),Y(1))
circuit.add_gate(merged_gate)
circuit.add_RX_gate(1,0.5)
circuit.update_quantum_state(state)

observable = Observable(3)
observable.add_operator(2.0, "X 2 Y 1 Z 0")
observable.add_operator(-3.0, "Z 2")
value = observable.get_expectation_value(state)
print(value)

Python Tutorial

Quantum states

Generate quantum states

Generate \(n\) qubit quantum states using QuantumState class and initialize it as \(\left|0\right>^{\otimes n}\).

[43]:
from qulacs import QuantumState
# Generate 2 qubit states
n = 2
state = QuantumState(n)
print(state)
 *** Quantum State ***
 * Qubit Count : 2
 * Dimension   : 4
 * State vector :
(1,0)
(0,0)
(0,0)
(0,0)

You can not generate the quantum states if the memory is not sufficient.

With the memory of a typical laptop or desktop computer, the limit of qubits you can create is about 26, 27 qubits.

Initialize quantum states

The generated quantum state can be initialized to a computational basis using the set_computational_basis or to a random state using the set_Harr_random_state.

Note that in Qulacs, the subscripts of the qubits start from 0, and the rightmost bit is the 0-th qubit when written as \(\ket{0000}\) (In other libraries and textbooks, the leftmost bit may be the 0-th qubit).

[44]:
from qulacs import QuantumState

n = 2
state = QuantumState(n)

# Initialize as |00>
state.set_zero_state()

# Initialize as |01>
state.set_computational_basis(0b01)

# Generate random initial state
state.set_Haar_random_state()
print(state)

# Generate random initial state with specifying seed
seed = 0
state.set_Haar_random_state(seed)
print(state)
 *** Quantum State ***
 * Qubit Count : 2
 * Dimension   : 4
 * State vector :
 (0.431665,0.175902)
 (-0.5087,-0.239707)
(0.151328,-0.478811)
(0.0969414,0.452692)

 *** Quantum State ***
 * Qubit Count : 2
 * Dimension   : 4
 * State vector :
 (-0.13535,-0.226344)
 (-0.214236,0.181293)
(-0.360441,-0.264813)
 (-0.241755,0.770192)

Obtain data of quantum state

A state vector of a quantum state can be obtained as a numpy array with get_vector function. And you can set a quantum state by giving a numpy array or a list in the load function.

[45]:
import numpy as np
from qulacs import QuantumState

n = 2
state = QuantumState(n)

# Get the state vector
vec = state.get_vector()
print(type(vec), vec.dtype)
print(vec)

# Set the state vector
myvec = np.array([0.5,0.5,0.5,0.5])
state.load(myvec)
print(state)
<class 'numpy.ndarray'> complex128
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 *** Quantum State ***
 * Qubit Count : 2
 * Dimension   : 4
 * State vector :
(0.5,0)
(0.5,0)
(0.5,0)
(0.5,0)

Copy and load quantum state data

The quantum state can be copied and loaded from other quantum state data.

[46]:
from qulacs import QuantumState
n = 5
state = QuantumState(n)
state.set_computational_basis(0b00101)
# Copy to generate another quantum state
second_state = state.copy()
print(second_state.get_vector())
# Generate a new quantum state, and copy from an existing quantum state
third_state = QuantumState(n)
third_state.load(state)
print(third_state.get_vector())
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j
 0.+0.j 0.+0.j]
Operate classic registers

The Quantum state can be read and written as a classic register.

[47]:
from qulacs import QuantumState
n = 5
state = QuantumState(n)
state.set_zero_state()
# Set the 3rd classical register as 1
register_position = 3
register_value = 1
state.set_classical_value(register_position, register_value)
# Obtain the value of the 3rd classical register
obtained_value = state.get_classical_value(register_position)
print(obtained_value)
1
Calculate quantum states

For a quantum state, information about the quantum state can be computed without changing the state of the quantum state. For example, the probability of getting 0 when measuring a qubit with a given index can be calculated with the get_zero_probability function.

[48]:
from qulacs import QuantumState

n = 5
state = QuantumState(n)
state.set_Haar_random_state(0)

# Calculate the probability to get 0 in measurement of the qubit in the given index at Z-basis
index = 3
zero_probability = state.get_zero_probability(index)
print("prob_meas_3rd : ",zero_probability)
prob_meas_3rd :  0.5199371283324116

The sampling function can be used to sample the results of a quantum state measurement. The argument of the function is the number of data to sample.

[49]:
import numpy as np
from qulacs import QuantumState

n = 2
state = QuantumState(n)
state.load([1/np.sqrt(2), 0, 0.5, 0.5])
data = state.sampling(10)
print(data)
# Show in binary format
print([format(value, "b").zfill(2) for value in data])
[3, 0, 2, 2, 3, 2, 2, 0, 0, 0]
['11', '00', '10', '10', '11', '10', '10', '00', '00', '00']

You can find many other functions in “Advanced” section.

Calculate the inner product of quantum states

The inner product of a quantum states can be calculated by the inner_product function.

[50]:
from qulacs import QuantumState
from qulacs.state import inner_product
n = 5
state_bra = QuantumState(n)
state_ket = QuantumState(n)
state_bra.set_Haar_random_state()
state_ket.set_computational_basis(0)
# Calculate the inner product
value = inner_product(state_bra, state_ket)
print(value)
(0.03141883589278555-0.015629285255538153j)

Quantum gate

Generate quantum gates

Quantum gates are defined in the qulacs.gate module. Several typical quantum gates are already defined in this module. For example, X gate can be generated as follows. By printing a quantum gate, you can print information about the gate.

[51]:
from qulacs.gate import X

target_index = 1
x_gate = X(target_index)
print(x_gate)
 *** gate info ***
 * gate name : X
 * target    :
 1 : commute X
 * control   :
 * Pauli     : yes
 * Clifford  : yes
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

Operation of quantum gates

Quantum gates can update a quantum state with the update_quantum_state function. The following example shows the X gate act on the 1st qubit.

[52]:
from qulacs import QuantumState
from qulacs.gate import X

n = 2
state = QuantumState(n)
print(state)

index = 1
x_gate = X(index)
x_gate.update_quantum_state(state)
print(state)
 *** Quantum State ***
 * Qubit Count : 2
 * Dimension   : 4
 * State vector :
(1,0)
(0,0)
(0,0)
(0,0)

 *** Quantum State ***
 * Qubit Count : 2
 * Dimension   : 4
 * State vector :
(0,0)
(0,0)
(1,0)
(0,0)

Various quantum gates

Below is a list of named gates that are often used. Any of the gates can update its quantum state using the update_quantum_state function. For other gates, see the Advanced chapter.

[53]:
import numpy as np

# Pauli gate, Hadamard gate, T gate
from qulacs.gate import X, Y, Z, H, T
target = 2
x_gate = X(target)
y_gate = Y(target)
z_gate = Z(target)
h_gate = H(target)
t_gate = T(target)

# Pauli rotation gate
from qulacs.gate import RX, RY, RZ
angle = np.pi / 4.0
rx_gate = RX(target, angle)
ry_gate = RY(target, angle)
rz_gate = RZ(target, angle)

# CNOT, CZ, SWAP gate
from qulacs.gate import CNOT, CZ, SWAP
control = 1
target2 = 1
cnot_gate = CNOT(control, target)
cz_gate = CZ(control, target)
swap_gate = SWAP(target, target2)
General quantum gates

To generate a gate by specifying the matrix of a quantum gate as a numpy array, use the class DenseMatrix. The first argument is the index to act on and the second is the matrix. For a single qubit gate, give an integer and a 2 x 2 matrix.

[54]:
from qulacs.gate import DenseMatrix

gate = DenseMatrix(1, [[0,1],[1,0]])
print(gate)
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 1 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(0,0) (1,0)
(1,0) (0,0)

To create a gate of size larger than 2 qubits, give a list of target subscripts as the first argument and a matrix as the second. When creating an \(n\)-qubit gate, the matrix must be of dimension \(2^n\).

[55]:
from qulacs.gate import DenseMatrix

gate = DenseMatrix([0,1], [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]])
print(gate)
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 0 : commute
 1 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(0,0) (1,0) (0,0) (0,0)
(1,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (1,0)
(0,0) (0,0) (1,0) (0,0)

Note that the indices that are lower bits when counting the columns and rows of a gated matrix correspond to the order of the subscripts given during gate generation, so the list of subscripts acting in the above example has a different meaning for [0,1] and [1,0]. The following shows the difference when the indices are swapped.

[56]:
from qulacs import QuantumState
from qulacs.gate import DenseMatrix

gate1 = DenseMatrix([0,1], [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]])
gate2 = DenseMatrix([1,0], [[0,1,0,0],[1,0,0,0],[0,0,0,1],[0,0,1,0]])
state = QuantumState(2)

state.set_zero_state()
gate1.update_quantum_state(state)
print(state.get_vector())

state.set_zero_state()
gate2.update_quantum_state(state)
print(state.get_vector())
[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
Append a control bit

A control bit can be added to the matrix gate using the add_control_qubit function. The first argument is the index of the control bit, the second argument is 0 or 1, and the operation is performed on target when the control bit has that value. For example, the CNOT gate performs a scan on target when the control bit has a value of 1, so the second argument is 1. Note that special named gates, such as the X gate, do not allow the control bit to be added. To add control bits to these, see “Conversion to General Matrix Gates” in the next section.

[57]:
from qulacs.gate import DenseMatrix

gate = DenseMatrix(1, [[0,1],[1,0]])
gate.add_control_qubit(3,1)
print(gate)
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 1 : commute
 * control   :
 3 : value 1
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(0,0) (1,0)
(1,0) (0,0)

While special named gates such as X gates can update quantum states faster than general matrix gates, they cannot be modified with functions like the add_control_qubit. To process a gate based on a special gate, use the to_matrix_gate function to convert the special gate to a general gate.

[58]:
from qulacs.gate import X, to_matrix_gate

gate = X(1)
print(gate)
gate = to_matrix_gate(gate)
print(gate)
gate.add_control_qubit(3,1)
 *** gate info ***
 * gate name : X
 * target    :
 1 : commute X
 * control   :
 * Pauli     : yes
 * Clifford  : yes
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 1 : commute X
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(0,0) (1,0)
(1,0) (0,0)

Obtain a gate matrix from a quantum gate

The gate matrix of the generated quantum gate can be obtained with the get_matrix function. An important note is that for gates with controlled-qubit, the controlled-qubit is not included in the gate matrix. Thus, for example, the gate matrix of a CNOT gate is a 2x2 matrix.

[59]:
from qulacs.gate import H, CNOT

h_gate = H(2)
matrix = h_gate.get_matrix()
print(matrix)
cnot_gate = CNOT(1,2)
matrix = cnot_gate.get_matrix()
print(matrix)
[[ 0.70710678+0.j  0.70710678+0.j]
 [ 0.70710678+0.j -0.70710678+0.j]]
[[0.+0.j 1.+0.j]
 [1.+0.j 0.+0.j]]

Quantum circuit

Construct the quantum circuit

Quantum circuits are defined as the QuantumCircuit class. You can add a gate to the QuantumCircuit class as add_<gatename>_gate or add a gate instance using the add_gate function. You can print the quantum circuit to see the information about the quantum circuit.

[60]:
from qulacs import QuantumCircuit

n = 5
circuit = QuantumCircuit(n)
circuit.add_H_gate(0)
circuit.add_X_gate(2)

from qulacs.gate import X
gate = X(2)
circuit.add_gate(gate)

print(circuit)
*** Quantum Circuit Info ***
# of qubit: 5
# of step : 2
# of gate : 3
# of 1 qubit gate: 3
Clifford  : yes
Gaussian  : no


Note: The quantum circuit added by add_gate is released from memory when the quantum circuit is released. Therefore, the assigned gate cannot be reused. If you want to reuse the gate given as an argument, make a copy of itself using gate.copy or use the add_gate_copy function.

Operation of quantum circuits

Quantum circuits can also update quantum states with update_quantum_state function like quantum gates.

[61]:
from qulacs import QuantumCircuit

n=3
circuit = QuantumCircuit(n)
circuit.add_H_gate(1)
circuit.add_RX_gate(2,0.1)

from qulacs import QuantumState
state = QuantumState(n)
circuit.update_quantum_state(state)
print(state)
 *** Quantum State ***
 * Qubit Count : 3
 * Dimension   : 8
 * State vector :
 (0.706223,0)
        (0,0)
 (0.706223,0)
        (0,0)
(0,0.0353406)
        (0,0)
(0,0.0353406)
        (0,0)

C++ Tutorial

Quantum states

Generate quantum states

Generate \(n\) qubit quantum states using QuantumState class and initialize it as \(|0\rangle^{\otimes n}\).

#include <cppsim/state.hpp>

int main(){
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();
    return 0;
}

You can not generate the quantum states if the memory is not sufficient.

With the memory of a typical laptop or desktop computer, the limit of qubits you can create is about 26, 27 qubits.

Obtain data of quantum states

The quantum state is expressed as an array of length \(2^n\). Note that if the quantum state is formed by GPU, and if the \(n\) is large, it can become an extremely heavy operation.

#include <cppsim/state.hpp>

int main(){
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    // If use GNU C++, obtain double_Complex array
    // If use MSVC, obtain std::complex<double> array
    const CTYPE* raw_data_c = state.data_c();

    // obtain std::complex<double> array
    const CPPCTYPE* raw_data_cpp = state.data_cpp();
}

If you want to set the quantum state directly to the specified array, it is recommended to create the corresponding quantum gate and perform it as an operation of the quantum gate.

Initialize quantum states

The generated quantum state can be initialized to a computational basis using the set_computational_basis or to a random state using the set_Harr_random_state.

Note that in Qulacs, the subscripts of the qubits start from 0, and the rightmost bit is the 0-th qubit when written as \(\ket{0000}\) (In other libraries and textbooks, the leftmost bit may be the 0-th qubit).

#include <cppsim/state.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();
    // Initialize as |00101>
    state.set_computational_basis(0b00101);
    // Generate random initial states
    state.set_Haar_random_state();
    // Generate random initial state with specifying seed
    state.set_Haar_random_state(0);
    return 0;
}
Copy and load quantum state data

The quantum state can be copied and loaded from other quantum state data.

#include <cppsim/state.hpp>

int main(){
    unsigned int n = 5;
    QuantumState state(n);
    state.set_computational_basis(0b00101);

    // Create new quantum state by copying
    auto second_state = state.copy();

    // Create a new quantum state and copy the existing state vector
    QuantumState third_state(n);
    third_state.load(&state);
    return 0;
}
Operate classic registers

The quantum state can be read and written as a classic register.

#include <cppsim/state.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    // Set the 3rd classical register as 1
    int register_position = 3;
    int register_value = 1;
    state.set_classical_bit(register_position, register_value);

    // Obtain the value of the 3rd classical register
    int obtained_value;
    obtained_value = state.get_classical_bit(register_position);
    return 0;
}
Calculate quantum states

The following operations do not change quantum states. Calculations that changes quantum states are performed by quantum gates or quantum circuits.

#include <cppsim/state.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    // Calculate norm
    double norm = state.get_squared_norm();
    // Calculate the entropy when measured in z-basis
    double entropy = state.get_entropy();

    // Calculate the probability that the index-th qubit is 0 when measured in z-basis
    unsigned int index = 3;
    double zero_prob = state.get_zero_probability(index);

    // Calculate marginal probabilities
    // (Here is an example of the probability that 0,3-th qubit is measured as 0 and 1,2-th qubit is measured as 1)
    std::vector<unsigned int> value_list = { 0,1,1,0,2 };
    double marginal_prob = state.get_marginal_probability(value_list);
    return 0;
}
Calculate the inner product of quantum states

The inner product of quantum states can be calculated by the inner_product function.

#include <cppsim/state.hpp>

int main(){
    unsigned int n = 5;
    QuantumState state_ket(n);
    state_ket.set_zero_state();

    QuantumState state_bra(n);
    state_bra.set_Haar_random_state();

    // Calculate the inner product
    std::complex<double> value = state::inner_product(&state_ket, &state_bra);
    return 0;
}

Quantum Gate

Generate and operate quantum gates

The quantum gate implemented by default is generated through the function of gate_factory. This quantum gate can operate on the quantum state specified by the argument of update_quantum_state. The quantum gate generated by gate_factory is not released automatically, so you must release it.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    // operation of X gata
    unsigned int index = 3;
    auto x_gate = gate::X(index);
    x_gate->update_quantum_state(&state);

    // Rotation by PI/2 using Y gate
    double angle = M_PI / 2.0;
    auto ry_gate = gate::RY(index, angle);
    ry_gate->update_quantum_state(&state);

    delete x_gate;
    delete ry_gate;
    return 0;
}

Quantum gates defined in the gate namespace are as following:

  • Single-qubit Pauli operation: Identity, X, Y, Z

  • Single-qubit Clifford operation: H, S, Sdag, T, Tdag, sqrtX, sqrtXdag, sqrtY, sqrtYdag

  • Two-qubit Clifford operation: CNOT, CZ, SWAP

  • Single-qubit Pauli rotation: RX, RY, RZ

  • General Pauli operation: Pauli, PauliRotation

  • IBMQ basis-gate: U1, U2, U3

  • General gate: DenseMatrix

  • Measurement : Measurement

  • Noise : BitFlipNoise, DephasingNoise, IndepenedentXZNoise, DepolarizingNoise

Rotation gates RX, RY, and RZ operate as Pauli rotation \(\exp(i\frac{\theta}{2}P)\) based on corresponding Pauli operator \(P\) and argument \(\theta\). Please check the API documents for details of each gate.

Merge quantum gates

You can generate a new single quantum gate by merging the quantum gates that continue to operate in sequence. You have to release the synthesized gate by yourself.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    unsigned int index = 3;
    auto x_gate = gate::X(index);

    double angle = M_PI / 2.0;
    auto ry_gate = gate::RY(index, angle);

    // combine X, RY in the successive operation order
    auto x_and_ry_gate = gate::merge(x_gate, ry_gate);

    x_and_ry_gate->update_quantum_state(&state);

    delete x_gate;
    delete ry_gate;
    delete x_and_ry_gate;
    return 0;
}
Sum of quantum gate matrices

A new gate can be generated by summing gates. (Not available for gates with control-qubit, because that operation is undefined yet.)

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>

int main() {
    auto gate00 = gate::merge(gate::P0(0), gate::P0(1));
    auto gate11 = gate::merge(gate::P1(0), gate::P1(1));
    // |00><00| + |11><11|
    auto proj_00_or_11 = gate::add(gate00, gate11);
    std::cout << proj_00_or_11 << std::endl;

    auto gate_ii_zz = gate::add(gate::Identity(0), gate::merge(gate::Z(0), gate::Z(1)));
    auto gate_ii_xx = gate::add(gate::Identity(0), gate::merge(gate::X(0), gate::X(1)));
    auto proj_00_plus_11 = gate::merge(gate_ii_zz, gate_ii_xx);
    // ((|00>+|11>)(<00|+<11|))/2 = (II + ZZ)(II + XX)/4
    proj_00_plus_11->multiply_scalar(0.25);
    std::cout << proj_00_plus_11 << std::endl;
    return 0;
}
Special quantum gate and common quantum gate

In cppsim, the basic quantum gates are divided into the following two ways:

  • Special gate: There are dedicated speed-up functions for utilizing the special gate.

  • Common gate: The gate holds the gate matrix and operates by multiplying the matrix.

The special gate is faster than the common gate because of the dedicated functions. But in a special gate, operations that change the function of a quantum gate, such as increasing the number of control qubits, cannot be performed later. This kind of change can be made only when the special gate is transformed into a common gate, which can be realized by gate::to_matrix_gate.

Here’s an example:

#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    unsigned int index = 3;
    auto x_gate = gate::X(index);

    // Add control qubit so that only operates when 1st-qubit is 0
    auto x_mat_gate = gate::to_matrix_gate(x_gate);
    unsigned int control_index = 1;
    unsigned int control_with_value = 0;
    x_mat_gate->add_control_qubit(control_index, control_with_value);

    x_mat_gate->update_quantum_state(&state);

    delete x_gate;
    delete x_mat_gate;
    return 0;
}

Please check the API documents for details of the special quantum gate.

Obtain the gate matrix of the quantum gate

The gate matrix of the generated quantum gate can be obtained, but gate matrices do not include the control qubit. Especially, note that gates without gate matrix (ex. \(n\)-qubit Pauli rotation gate) require a very long time and memory to obtain the matrix.

#include <iostream>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>

int main(){
    unsigned int index = 3;
    auto x_gate = gate::X(index);

    // obtain the matrix element
    // ComplexMatrix is a complex matrix type with RowMajor by Eigen::MatrixXcd
    ComplexMatrix matrix;
    x_gate->set_matrix(matrix);
    std::cout << matrix << std::endl;
    return 0;
}
Obtain information about quantum gate

Debug information of quantum gate can be shown by using ostream. Note that if the gate matrix of the quantum gate is very large, it takes a long time. Quantum gates with dedicated functions do not display their gate matrix.

#include <iostream>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>

int main(){

    unsigned int index = 3;
    auto x_gate = gate::X(index);

    std::cout << x_gate << std::endl;

    delete x_gate;
    return 0;
}
Implement of common quantum gate

Cppsim implements various maps of quantum information in the following forms.

Unitary operation

Implemented as the quantum gate.

Projection operator and Kraus operator, etc.

Implemented as the quantum gate. In general, the norm of the quantum state is not preserved after the operation.

The gate can be generated by DenseMatrix.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>
#include <cppsim/gate_general.hpp>

int main() {
    ComplexMatrix one_qubit_matrix(2, 2);
    one_qubit_matrix << 0, 1, 1, 0;
    auto one_qubit_gate = gate::DenseMatrix(0, one_qubit_matrix);
    std::cout << one_qubit_gate << std::endl;

    ComplexMatrix two_qubit_matrix(4,4);
    two_qubit_matrix <<
        1, 0, 0, 0,
        0, 1, 0, 0,
        0, 0, 0, 1,
        0, 0, 1, 0;
    auto two_qubit_gate = gate::DenseMatrix({0,1}, two_qubit_matrix);
    std::cout << two_qubit_gate << std::endl;
    return 0;
}
Probabilistic unitary operations

With given multiple unitary operations and probability distributions, stochastic unitary operations can be created by Probabilistic function.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>
#include <cppsim/gate_general.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    unsigned int index = 3;
    auto x_gate = gate::X(index);
    auto z_gate = gate::Z(index);

    auto probabilistic_xz_gate = gate::Probabilistic({ 0.1,0.2 } , { x_gate,z_gate });
    auto depolarizing_gate = gate::DepolarizingNoise(index, 0.3);

    depolarizing_gate->update_quantum_state(&state);
    probabilistic_xz_gate->update_quantum_state(&state);
    return 0;
}
CPTP-map

CPTP-map can be created by giving the CPTP function a list of Kraus operators satisfying completeness.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>
#include <cppsim/gate_general.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    unsigned int index = 3;
    auto p0 = gate::P0(index);
    auto p1_fix = gate::merge(gate::P1(index), gate::X(index));

    auto correction = gate::CPTP({p0,p1_fix});
    auto noise = gate::BitFlipNoise(index,0.1);

    noise->update_quantum_state(&state);
    correction->update_quantum_state(&state);
    return 0;
}
POVM

Since it is the same as Instrument in numerical calculation, it is realized as Instrument.

Instrument

In addition to the general CPTP-map operation, Instrument is an operation that obtains the array subscripts of the randomly acting Kraus operator. For example, a measurement on the Z basis is to operate on the CPTP-map consisting of P0 and P1 and know which one was operated. In cppsim, this is achieved by specifying the information of the CPTP-map and the address of the classic register in which the subscripts of the operated Kraus operator are written in the Instrument function.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>
#include <cppsim/gate_general.hpp>

int main() {
    auto gate00 = gate::merge(gate::P0(0), gate::P0(1));
    auto gate01 = gate::merge(gate::P0(0), gate::P1(1));
    auto gate10 = gate::merge(gate::P1(0), gate::P0(1));
    auto gate11 = gate::merge(gate::P1(0), gate::P1(1));

    std::vector<QuantumGateBase*> gate_list = { gate00, gate01, gate10, gate11 };
    unsigned int classical_pos = 0;
    auto gate = gate::Instrument(gate_list, classical_pos);

    QuantumState state(2);
    state.set_Haar_random_state();

    std::cout << state << std::endl;
    gate->update_quantum_state(&state);
    unsigned int result = state.get_classical_value(classical_pos);
    std::cout << state << std::endl;
    std::cout << result << std::endl;
    return 0;
}
Adaptive

The operation is performed or not performed depending on the value written to the classical register. In cppsim, this is achieved by specifying a function that takes a register of type std::vector<unsigned int> as an argument and returns a bool type in the Adaptive function.

#define _USE_MATH_DEFINES
#include <cmath>
#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/gate_merge.hpp>
#include <cppsim/gate_matrix.hpp>
#include <cppsim/gate_general.hpp>

int main() {
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    unsigned int index = 3;
    auto h = gate::H(index);
    h->update_quantum_state(&state);

    auto meas = gate::Measurement(index,0);
    meas->update_quantum_state(&state);

    auto condition = [](const std::vector<UINT> reg){
        return reg[0]==1;
    };
    auto correction = gate::Adaptive(gate::X(index), condition);
    correction->update_quantum_state(&state);
    return 0;
}
CP-map

If Kraus rank is 1, please treat it as a single Kraus operator as described above. In other cases, please adjust the Kraus operator so that it becomes TP, and then adjust it by applying the Identity operator multiplied by a constant with the multiply_scalar() function.

Quantum Circuits

Construct the quantum circuit

A quantum circuit is represented as a set of quantum gates. For example, you can construct a quantum circuit as follows:

#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/circuit.hpp>

int main(){
    unsigned int n = 5;
    QuantumState state(n);
    state.set_zero_state();

    // Define quantum circuit
    QuantumCircuit circuit(n);

    // Add gate to quantum circuit
    for(int i=0;i<n;++i){
        circuit.add_H_gate(i);
    }

    // Gate defined by user can also be added
    for(int i=0;i<n;++i){
        circuit.add_gate(gate::H(i));
    }

    // Operate quantum circuit to state
    circuit.update_quantum_state(&state);
    return 0;
}

Note: the quantum circuit added by add_gate is released from memory when the quantum circuit is released. Therefore, the assigned gate cannot be reused. If you want to reuse the gate given as an argument, make a copy of itself using gate.copy or use the add_gate_copy function. But in this case, you have to release the gate by yourself.

Calculate and optimize the depth of quantum circuits

By merging quantum gates into a single one, the number of quantum gates can be reduced and the time required for numerical calculations can be reduced. (Of course, the total calculation time will not necessarily be reduced if the number of target qubits is increased or if a quantum gate with a dedicated function is merged into a quantum gate without a dedicated function.)

The code below uses the optimize function to repeat merging the quantum gates of the quantum circuit until the target qubit becomes three by greedy algorithm.

#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/circuit.hpp>
#include <cppsim/circuit_optimizer.hpp>

int main() {
    unsigned int n = 5;
    unsigned int depth = 10;
    QuantumCircuit circuit(n);
    for (int d = 0; d < depth; ++d) {
        for (int i = 0; i < n; ++i) {
            circuit.add_gate(gate::H(i));
        }
    }

    // 量子回路の最適化
    QuantumCircuitOptimizer opt;
    unsigned int max_block_size = 3;
    opt.optimize(&circuit, max_block_size);
    return 0;
}
Obtain debug information of quantum circuits

The same as the quantum gate, debug information of the quantum circuit can be shown by using ostream.

#include <cppsim/state.hpp>
#include <cppsim/gate_factory.hpp>
#include <cppsim/circuit.hpp>

int main() {
    unsigned int n = 5;
    unsigned int depth = 10;
    QuantumCircuit circuit(n);
    for (int d = 0; d < depth; ++d) {
        for (int i = 0; i < n; ++i) {
            circuit.add_gate(gate::H(i));
        }
    }

    // Output information of quantum circuit
    std::cout << circuit << std::endl;
    return 0;
}

Observables

Generate observables

Observables are represented as a set of Pauli operators. The Pauli operator can be defined as follows:

#include <cppsim/observable.hpp>
#include <string>

int main() {
    unsigned int n = 5;
    double coef = 2.0;
    std::string Pauli_string = "X 0 X 1 Y 2 Z 4";
    Observable observable(n);
    observable.add_operator(coef,Pauli_string.c_str());
    return 0;
}
Cooperate with OpenFermion

Observables can be generated from files in the following formats generated using OpenFermion. At this time, the observable has the minimum size necessary to generate it. For example, it is possible to generate an observable by reading an observable obtained using OpenFermion such as the following.

from openfermion.ops import FermionOperator
from openfermion.transforms import bravyi_kitaev

h_00 = h_11 = -1.252477
h_22 = h_33 = -0.475934
h_0110 = h_1001 = 0.674493
h_2332 = h_3323 = 0.697397
h_0220 = h_0330 = h_1221 = h_1331 = h_2002 = h_3003 = h_2112 = h_3113 = 0.663472
h_0202 = h_1313 = h_2130 = h_2310 = h_0312 = h_0132 = 0.181287

fermion_operator = FermionOperator('0^ 0', h_00)
fermion_operator += FermionOperator('1^ 1', h_11)
fermion_operator += FermionOperator('2^ 2', h_22)
fermion_operator += FermionOperator('3^ 3', h_33)

fermion_operator += FermionOperator('0^ 1^ 1 0', h_0110)
fermion_operator += FermionOperator('2^ 3^ 3 2', h_2332)
fermion_operator += FermionOperator('0^ 3^ 3 0', h_0330)
fermion_operator += FermionOperator('1^ 2^ 2 1', h_1221)

fermion_operator += FermionOperator('0^ 2^ 2 0', h_0220-h_0202)
fermion_operator += FermionOperator('1^ 3^ 3 1', h_1331-h_1313)

fermion_operator += FermionOperator('0^ 1^ 3 2', h_0132)
fermion_operator += FermionOperator('2^ 3^ 1 0', h_0132)

fermion_operator += FermionOperator('0^ 3^ 1 2', h_0312)
fermion_operator += FermionOperator('2^ 1^ 3 0', h_0312)

## Bravyi-Kitaev transformation
bk_operator = bravyi_kitaev(fermion_operator)

## output
fp = open("H2.txt", 'w')
fp.write(str(bk_operator))
fp.close()

The H2.txt file generated by the above Python code has the following format.

(-0.8126100000000005+0j) [] +
(0.04532175+0j) [X0 Z1 X2] +
(0.04532175+0j) [X0 Z1 X2 Z3] +
(0.04532175+0j) [Y0 Z1 Y2] +
(0.04532175+0j) [Y0 Z1 Y2 Z3] +
(0.17120100000000002+0j) [Z0] +
(0.17120100000000002+0j) [Z0 Z1] +
(0.165868+0j) [Z0 Z1 Z2] +
(0.165868+0j) [Z0 Z1 Z2 Z3] +
(0.12054625+0j) [Z0 Z2] +
(0.12054625+0j) [Z0 Z2 Z3] +
(0.16862325+0j) [Z1] +
(-0.22279649999999998+0j) [Z1 Z2 Z3] +
(0.17434925+0j) [Z1 Z3] +
(-0.22279649999999998+0j) [Z2]

You can create an observable from such a file through a function as follows:

#include <cppsim/observable.hpp>
#include <string>

int main() {
    unsigned int n = 5;
    std::string filename = "H2.txt";
    Observable* observable = observable::create_observable_from_openfermion_file(filename);
    delete observable;
    return 0;
}
Evaluate observable

An evaluation of the expected value of the observable for the state can be obtained.

#include <cppsim/observable.hpp>
#include <cppsim/state.hpp>
#include <string>

int main() {
    unsigned int n = 5;
    double coef = 2.0;
    std::string Pauli_string = "X 0 X 1 Y 2 Z 4";
    Observable observable(n);
    observable.add_operator(coef, Pauli_string.c_str());

    QuantumState state(n);
    observable.get_expectation_value(&state);
    return 0;
}
Rotation of Observable

The rotation of Observable \(H\), \(e^{i\theta H}\), is performed by Trotter expansion. num_repeats defaults as the following code, but can be optionally specified by the user.

#include <cppsim/circuit.hpp>
#include <cppsim/state.hpp>
#include <cppsim/observable.hpp>

int main() {
    UINT n;
    UINT num_repeats;
    double theta = 0.1;
    Observable* observable = observable::create_observable_from_openfermion_file("../test/cppsim/H2.txt");

    n = observable->get_qubit_count();
    QuantumState state(n);
    state.set_computational_basis(0);

    QuantumCircuit circuit(n);
    num_repeats = (UINT)std::ceil(theta * (double)n* 100.);
    circuit.add_observable_rotation_gate(*observable, theta, num_repeats);
    circuit.update_quantum_state(&state);

    auto result = observable->get_expectation_value(&state);
    std::cout << result << std::endl;
    delete observable;
    return 0;
}

Parametric Quantum Circuits

Defining a quantum circuit as the ParametricQuantumCircuit class allows you to use some functions that are useful for optimizing quantum circuits using variational methods, in addition to the usual functions of the QuantumCircuit class.

Examples of parametric quantum circuits

Quantum gates with one rotation angle (X-rot, Y-rot, Z-rot, multi_qubit_pauli_rotation) can be added to quantum circuits as parametric quantum gates. For quantum gates added as parametric gates, the number of parametric gates can be extracted after the quantum circuit is constructed, and the rotation angle can be changed later.

#include <cppsim/state.hpp>
#include <vqcsim/parametric_circuit.hpp>
#include <cppsim/utility.hpp>

int main(){
    const UINT n = 3;
    const UINT depth = 10;

    // create n-qubit parametric circuit
    ParametricQuantumCircuit* circuit = new ParametricQuantumCircuit(n);
    Random random;
    for (UINT d = 0; d < depth; ++d) {
        // add parametric X,Y,Z gate with random initial rotation angle
        for (UINT i = 0; i < n; ++i) {
            circuit->add_parametric_RX_gate(i, random.uniform());
            circuit->add_parametric_RY_gate(i, random.uniform());
            circuit->add_parametric_RZ_gate(i, random.uniform());
        }
        // add neighboring two-qubit ZZ rotation
        for (UINT i = d % 2; i + 1 < n; i+=2) {
            circuit->add_parametric_multi_Pauli_rotation_gate({ i,i + 1 }, { 3,3 }, random.uniform());
        }
    }

    // get parameter count
    UINT param_count = circuit->get_parameter_count();

    // get current parameter, and set shifted parameter
    for (UINT p = 0; p < param_count; ++p) {
        double current_angle = circuit->get_parameter(p);
        circuit->set_parameter(p, current_angle + random.uniform());
    }

    // create quantum state and update
    QuantumState state(n);
    circuit->update_quantum_state(&state);

    // output state and circuit info
    std::cout << state << std::endl;
    std::cout << circuit << std::endl;

    // release quantum circuit
    delete circuit;
}

Qulacs Python Advanced Guide

This chapter is for those who are familiar with the terminology of quantum information and want fine tuning for numerical calculations. For more information on terminology, please see the textbook Quantum Computation and Quantum Information by M.A. Nielsen et al..

Quantum States

This class allocates and manages \(2^n\) complex arrays on the CPU/GPU with the precision of complex128.

Create and Destroy

Necessary memory is secured at the time of instance creation and released when the instance is destroyed, but you can explicitly destroy it to release the memory with del.

[9]:
from qulacs import QuantumState
n = 2
state = QuantumState(n)
print(state)
del state
 *** Quantum State ***
 * Qubit Count : 2
 * Dimension   : 4
 * State vector :
(1,0)
(0,0)
(0,0)
(0,0)

Transform between quantum state and numpy array

Transformation between quantum state and numpy array can be realized by get_vector or load function. In principle, it is not checked whether the norm is saved. While get_vector returns all the element as an array, get_amplitude can be used to quickly get a single element.

[1]:
from qulacs import QuantumState

state = QuantumState(2)
vec = state.get_vector()
print(vec)
state.load([0,1,2,3])
print(state.get_vector())
print(state.get_amplitude(2))
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
[0.+0.j 1.+0.j 2.+0.j 3.+0.j]
(2+0j)
Copy quantum states

Quantum states can generate new instances of the same state by copy. By giving a quantum state to the load function, it is possible to copy a quantum vector of another quantum state without allocating a new area in the existing quantum state. This allows you to reuse the already allocated space. You can use the allocate_buffer function if you want to allocate a state vector of the same size as the quantum state you already have and without copying the state.

[10]:
from qulacs import QuantumState

initial_state = QuantumState(3)
buffer = initial_state.allocate_buffer()
for ind in range(10):
    buffer.load(initial_state)
    # some computation and get results
Initialization of quantum state

The following is an function initializing a quantum state to a specific state.

[4]:
from qulacs import QuantumState

n = 3
state = QuantumState(n)
# Initialize as |0> state
state.set_zero_state()
print(state.get_vector())

# Initialize the specified value to the calculation base in binary notation
state.set_computational_basis(0b101)
print(state.get_vector())

# Initialize to random pure state with Haar measure using argument value as seed
# If no value is specified, the time function is used as a seed. Pseudo random number uses xorshift.
state.set_Haar_random_state(0)
print(state.get_vector())
[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j]
[ 0.17875932+0.12507972j  0.28161322-0.20162504j  0.21880416-0.04754893j
  0.01570731+0.46979145j -0.0216192 +0.46023702j -0.20700612+0.09443371j
 -0.03203312+0.3305667j   0.43080876+0.03745933j]
Check quantum state

The following example is a list of functions to check quantum state information without changing the quantum state.

[5]:
from qulacs import QuantumState

n = 5
state = QuantumState(n)
state.set_Haar_random_state(0)

# Get quantum bit numbers
qubit_count = state.get_qubit_count()
print("qubit_count", qubit_count)

# Get the probability that the specified qubit will be measured as 0
prob = state.get_zero_probability(1)
print("zero_prob_1", prob)

# Get arbitrary marginal probabilities
# Argument is an array of the same length as the number of qubits
# Specify 0,1,2. 0,1 is the probability of the subscript measured at that value
# 2 means that bit is peripheralized.
# For example, calculation of the probability that the third is measured as 0 and the 0th is measured as 1:
prob = state.get_marginal_probability([1,2,2,0,2])
print("marginal_prob", prob)

# Get the entropy of the probability distribution when measured on the Z basis
ent = state.get_entropy()
print("entropy", ent)

# Get squared norm (<a|a>)
# Because the operation may not be Trace preserving, the norm of state does not necessarily to be 1.
sq_norm = state.get_squared_norm()
print("sqaured_norm", sq_norm)

# Measure and sample all the qubits on Z-basis as many times as given by the argument.
# Returns a list of integers converted from the resulting binaries.
samples = state.sampling(10)
print("sampling", samples)

# You can supply a random seed as second argument.
# If the same seed is given, always returns the same sampling result.
samples_with_seed = state.sampling(10, 314)
print("sampling (with seed)", samples_with_seed)

# Get a character string indicating whether the state vector is on CPU or GPU
dev_type = state.get_device_name()
print("device", dev_type)
qubit_count 5
zero_prob_1 0.6177236324405834
marginal_prob 0.3266606041128599
entropy 3.1462789915919283
sqaured_norm 0.9999999999999998
sampling [10, 4, 4, 28, 21, 9, 22, 1, 21, 21]
device cpu
Deformation of quantum state

The following functions modify a quantum state.

[6]:
from qulacs import QuantumState
state = QuantumState(2)
state.set_computational_basis(0)
buffer = QuantumState(2)
buffer.set_computational_basis(2)
print("state" , state.get_vector())
print("buffer", buffer.get_vector())

# Sum of quantum state (state <- state+buffer)
# Add the buffer state to the state to create a superposition state.
# The norm after the operation generally is not 1.
state.add_state(buffer)
print("added", state.get_vector())

# Product of quantum state and complex number
# Multiplies all elements by the complex number of the argument.
# The norm after operation generally is not 1.
coef = 0.5 + 0.1j
state.multiply_coef(coef)
print("mul_coef", state.get_vector())

# Pruduct of a quantum state and complex numbers specified by an index of each element
# Multiplies the amplitude of |00> by `coef_func(0)`, the amplitude of |01> by `coef_func(1)`.
# The norm after operation generally is not 1.
def coef_func(i: int) -> complex:
    assert 0 <= i < 2**2
    return 1j**i
state.multiply_elementwise_function(coef_func)
print("mul_elementwise_func", state.get_vector())

# Normalize quantum states
# Provide the current squared norm as an argument.
squared_norm = state.get_squared_norm()
print("sq_norm", squared_norm)
state.normalize(squared_norm)
print("normalized", state.get_vector())
print("sq_norm", state.get_squared_norm())
state [1.+0.j 0.+0.j 0.+0.j 0.+0.j]
buffer [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
added [1.+0.j 0.+0.j 1.+0.j 0.+0.j]
mul_coef [0.5+0.1j 0. +0.j  0.5+0.1j 0. +0.j ]
sq_norm 0.52
normalized [0.69337525+0.13867505j 0.        +0.j         0.69337525+0.13867505j
 0.        +0.j        ]
sq_norm 0.9999999999999998
Opetation on classic registers

Quantum states have classical registers as integer arrays with variable length. The classical register is used to write the result of the Instrument operation or to describe a gate that executes conditions as the result of the classical register. The value of a classic register that has not yet been written is 0. The classical register is copied at the same time when the quantum state is copied by the copy and load functions.

[7]:
from qulacs import QuantumState
state = QuantumState(3)
position = 0
# Write the value to `position`-th register
state.set_classical_value(position, 20)
# Get the value of the `position`-th register
obtained = state.get_classical_value(position)
print(obtained)
20
Calculation between quantum states

The inner product and tensor product between quantum states can be obtained by inner_product and tensor_product respectively.

[2]:
from qulacs import QuantumState
from qulacs.state import inner_product, tensor_product

n = 5
state_bra = QuantumState(n)
state_ket = QuantumState(n)
state_bra.set_Haar_random_state()
state_ket.set_computational_basis(0)

# Calculation of inner product
value = inner_product(state_bra, state_ket)
print(value)

n1 = 1
state_ket1 = QuantumState(n1)
state_ket1.set_computational_basis(1)
n2 = 2
state_ket2 = QuantumState(n2)
state_ket2.set_computational_basis(2)

# Calculation of tensor product
tensor_product_state = tensor_product(state_ket1, state_ket2)
print(tensor_product_state.get_vector())
(0.0989867916539525+0.1746302369139219j)
[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j]
Swap and delete qubits

You can swap indices of a qubit with permutate_qubit(). You can get a projection onto a specified qubit with drop_qubit().

[3]:
from qulacs import QuantumState
from qulacs.state import permutate_qubit, drop_qubit

n = 3
state = QuantumState(n)
state.set_Haar_random_state()
print("original:", state.get_vector())
# new qubit 0 is old qubit 1
# new qubit 1 is old qubit 2,
# new qubit 2 is old qubit 0,
permutate = permutate_qubit(state, [1, 2, 0])
print("permutate:", permutate.get_vector())
print()

n = 3
state = QuantumState(n)
state.set_Haar_random_state()
print("original:", state.get_vector())
state0 = drop_qubit(state, [1], [0])
print("projection to 0:", state0.get_vector()) # projection: qubit 1 is 0
state1 = drop_qubit(state, [1], [1])
print("projection to 1:", state1.get_vector()) # projection: qubit 1 is 1
original: [-0.25576074+0.00597572j -0.24574049-0.48099785j -0.13878694+0.39066629j
 -0.3435684 -0.36335378j  0.04902662+0.04174407j -0.15300638+0.2653734j
  0.02229379-0.12168674j  0.24967543+0.21268185j]
permutate: [-0.25576074+0.00597572j -0.13878694+0.39066629j  0.04902662+0.04174407j
  0.02229379-0.12168674j -0.24574049-0.48099785j -0.3435684 -0.36335378j
 -0.15300638+0.2653734j   0.24967543+0.21268185j]

original: [-0.11109937+0.50580828j  0.00858304-0.02332304j -0.03613546+0.40230458j
 -0.28334918+0.1866249j   0.30208259+0.11389186j  0.47513828+0.042232j
 -0.11088426-0.22169112j -0.22951727+0.08391248j]
projection to 0: [-0.11109937+0.50580828j  0.00858304-0.02332304j  0.30208259+0.11389186j
  0.47513828+0.042232j  ]
projection to 1: [-0.03613546+0.40230458j -0.28334918+0.1866249j  -0.11088426-0.22169112j
 -0.22951727+0.08391248j]
Calculate partial trace

With partial_trace(), you can obtain a partial trace of a given qubit of a given quantum state as a density matrix. The indices of the converted qubits are reassigned based on the order of the qubits before conversion.

[4]:
from qulacs import QuantumState, DensityMatrix
from qulacs.gate import H, X
from qulacs.state import partial_trace

state = QuantumState(3)
state.set_computational_basis(0)
H(0).update_quantum_state(state)
X(1).update_quantum_state(state)
print(state.get_vector())

trace = partial_trace(state, [1])
print(trace.get_matrix())

dm_state = DensityMatrix(3)
dm_state.set_computational_basis(0)
H(0).update_quantum_state(dm_state)
X(1).update_quantum_state(dm_state)
print(dm_state.get_matrix())

trace = partial_trace(dm_state, [1])
print(trace.get_matrix())
[0.        +0.j 0.        +0.j 0.70710678+0.j 0.70710678+0.j
 0.        +0.j 0.        +0.j 0.        +0.j 0.        +0.j]
[[0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]
 [0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]
[[0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0.5+0.j 0.5+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0.5+0.j 0.5+0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]]
[[0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]
 [0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]
Calculation using GPU

When Qulacs is installed from qulacs-gpu package, QuantumStateGpu is available. Except the different class name, the usage is the same as QuantumState.

from qulacs import QuantumStateGpu
state = QuantumStateGpu(2)
print(state)
# print(state.get_device_name())
# gpu

Though the usage is the same as QuantumState, there are two aspects to keep in mind:

  • The get_vector function takes a long time because it requires copying between the GPU and CPU. This function should be avoided whenever possible.

  • inner_product between CPU / GPU states cannot be calculated. It is possible to load a state vector between the GPU and CPU state vectors, but it is time consuming and should be avoided.

DensityMatrix

DensityMatrix is a class to hold a quantum state as a density matrix. While StateVector can hold a pure state, DensityMatrix can also hold a mixed state, or probabilistic mixture of multiple states. Use the density matrix \(\sum_i p_i\ket{\psi_i}\bra{\psi_i}\) when each state is \(\ket{\psi_i}\) with probability \(p_i\). This may seem redundant since there are no multi-state composite states in this chapter, but it will be useful when using Probabilistic gates, etc., described below. Basically, DensityMatrix can be operated in the same way as QuantumState.

Generate and delete

The necessary memory is allocated when the instance is created. The memory is released when Python interpreter destroys the instance, but can be released with del if you want to explicitly destroy it to free memory.

[5]:
from qulacs import QuantumState
n = 2
state = DensityMatrix(n)
print(state)
del state
 *** Density Matrix ***
 * Qubit Count : 2
 * Dimension   : 4
 * Density matrix :
(1,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (0,0)

Conversion between quantum states and numpy array

You can convert quantum states and numpy array mutually with get_matrix and load. If the array is 1-dimensional, it is converted from a state vector to a density matrix, and if it is 2-dimensional, it is read as a density matrix. Basically, whether the norm is conserved or not is not checked.

[6]:
from qulacs import DensityMatrix

state = DensityMatrix(2)
mat = state.get_matrix()
print(mat)
state.load([0,1,2,3])
print(state.get_matrix())
state.load([[0,1,2,3], [1,2,3,4], [2,3,4,5], [3,4,5,6]])
print(state.get_matrix())
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]
[[0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 1.+0.j 2.+0.j 3.+0.j]
 [0.+0.j 2.+0.j 4.+0.j 6.+0.j]
 [0.+0.j 3.+0.j 6.+0.j 9.+0.j]]
[[0.+0.j 1.+0.j 2.+0.j 3.+0.j]
 [1.+0.j 2.+0.j 3.+0.j 4.+0.j]
 [2.+0.j 3.+0.j 4.+0.j 5.+0.j]
 [3.+0.j 4.+0.j 5.+0.j 6.+0.j]]
Copy between quantum states

A quantum state can be instantiated by copy to create a new instance of itself. Also, by giving a quantum state to the load function, you can copy the quantum vector or density matrix of another quantum state without allocating new space in the existing quantum state. This allows you to reuse the space you have already allocated. If you want to allocate a density matrix of the same size as the quantum state you already have, but do not need to copy the state, you can use the allocate_buffer function.

[7]:
from qulacs import QuantumState, DensityMatrix

initial_state = DensityMatrix(3)
copied_state = initial_state.copy()
buffer = initial_state.allocate_buffer()
buffer.load(initial_state)
state_vector = QuantumState(3)
buffer.load(state_vector)
Initialize quantum states

The following example shows functions to initialize a quantum state to a specific pure state.

[8]:
from qulacs import DensityMatrix

n = 2
state = DensityMatrix(n)

# Initialize as |0> state.
state.set_zero_state()
print(state.get_matrix())

# Initialize as computational basis specified in binary format.
state.set_computational_basis(0b10)
print(state.get_matrix())


# Initialize as a random pure state in Haar measure with the seed given as an argument.
# If you do not give the seed, `time` function is used for seed.
# Xorshift is used for psuedo random.
state.set_Haar_random_state(0)
print(state.get_matrix())
[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]
[[0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]
[[ 0.06955138-7.70125855e-20j -0.01203783+7.30292081e-02j
   0.10872467+4.57411642e-02j -0.14160694+1.58965333e-01j]
 [-0.01203783-7.30292081e-02j  0.07876443-6.51380568e-19j
   0.02921052-1.22078110e-01j  0.19142327+1.21174378e-01j]
 [ 0.10872467-4.57411642e-02j  0.02921052+1.22078110e-01j
   0.20004359-5.57982323e-18j -0.11681879+3.41628304e-01j]
 [-0.14160694-1.58965333e-01j  0.19142327-1.21174378e-01j
  -0.11681879-3.41628304e-01j  0.6516406 +8.34447617e-18j]]
Check quantum states

The following example shows functions to check information of quantum states without changing the states.

[9]:
from qulacs import DensityMatrix

n = 5
state = DensityMatrix(n)
state.set_Haar_random_state(0)

# Get quantum bit numbers
qubit_count = state.get_qubit_count()
print("qubit_count", qubit_count)

# Get the probability that the specified qubit will be measured as 0
prob = state.get_zero_probability(1)
print("zero_prob_1", prob)

# Get arbitrary marginal probabilities
# Argument is an array of the same length as the number of qubits
# Specify 0,1,2. 0,1 is the probability of the subscript measured at that value
# 2 means that bit is peripheralized.
# For example, calculation of the probability that the third is measured as 0 and the 0th is measured as 1:
prob = state.get_marginal_probability([1,2,2,0,2])
print("marginal_prob", prob)

# Get the entropy of the probability distribution when measured on the Z basis
ent = state.get_entropy()
print("entropy", ent)

# Get squared norm (<a|a>)
# Because the operation may not be Trace preserving, the norm of state does not necessarily to be 1.
sq_norm = state.get_squared_norm()
print("sqaured_norm", sq_norm)

# Measure and sample all the qubits on Z-basis as many times as given by the argument.
# Returns a list of integers converted from the resulting binaries.
samples = state.sampling(10)
print("sampling", samples)

# You can supply a random seed as second argument.
# If the same seed is given, always returns the same sampling result.
samples_with_seed = state.sampling(10, 314)
print("sampling (with seed)", samples_with_seed)

# Get a character string indicating whether the state vector is on CPU or GPU
dev_type = state.get_device_name()
print("device", dev_type)
qubit_count 5
zero_prob_1 0.46010755964245975
marginal_prob 0.20030608663813235
entropy 3.108273642412474
sqaured_norm 0.9999999999999999
sampling [18, 28, 22, 24, 21, 11, 29, 19, 30, 6]
sampling (with seed) [23, 18, 28, 14, 17, 30, 9, 17, 16, 10]
device cpu
Deformation of quantum states

The following functions modify a quantum state. add_state and multiply_coef calculates for each element in a density matrix.

It is fundamentally different in behavior from the operation of the same name in ``QuantumState``, which corresponds to the quantum state

  • add_state of QuantumState creates superpositon, but add_state of DensityMatrix create mixed state

  • The operation corresponding to multiply_coef(z) of QuantumState is multiply_coef(abs(z)**2) for DensityMatrix

Using state.make_superposition() state.make_mixture() is recommended since add_state() multiply_coef() make users confused with those generated by QuantumState.

[10]:
from qulacs import DensityMatrix
state = DensityMatrix(2)
state.set_computational_basis(0)
buffer = DensityMatrix(2)
buffer.set_computational_basis(2)
print("state" , state.get_matrix())
print("buffer", buffer.get_matrix())

# Sum of quantum state (state <- state+buffer)
# Add the buffer state to the state to create a superposition state.
# The norm after the operation generally is not 1.
state.add_state(buffer)
print("added", state.get_matrix())

# Product of quantum state and complex number
# Multiplies all elements by the complex number of the argument.
# The norm after operation generally is not 1.
coef = 3.0
state.multiply_coef(coef)
print("mul_coef", state.get_matrix())

# Normalize quantum states
# Provide the current squared norm as an argument.
squared_norm = state.get_squared_norm()
print("sq_norm", squared_norm)
state.normalize(squared_norm)
print("normalized", state.get_matrix())
print("sq_norm", state.get_squared_norm())
state [[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]
buffer [[0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]
added [[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]
mul_coef [[3.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 3.+0.j 0.+0.j]
 [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]
sq_norm 6.0
normalized [[0.5+0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j]
 [0. +0.j 0. +0.j 0.5+0.j 0. +0.j]
 [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]
sq_norm 1.0
Operation on classical registers

DensityMatrix also has classical registers as integer arrays with variable length.

[ ]:
from qulacs import DensityMatrix
state = DensityMatrix(3)
position = 0
# Set the value at `position`-th register.
state.set_classical_value(position, 20)
# Get the value at `position`-th register.
obtained = state.get_classical_value(position)
print(obtained)
Creating superposition states and mixture states

You can create superposition states and mixture states by using make_superposition() make_mixture() in state module. These states can also be created by applying add_state() multiply_coef() to QuantumState DensityMatrix, but is deprecated due to low readability.

[ ]:
from qulacs import QuantumState, DensityMatrix
from qulacs.state import make_superposition, make_mixture
# from QuantumState |a> and |b>, create a superposition state p|a> + q|b>
a = QuantumState(2)
a.set_computational_basis(0b00)
b = QuantumState(2)
b.set_computational_basis(0b11)
p = 1 / 2
q = 1 / 2
c = make_superposition(p, a, q, b)
print(c.get_vector())
# from QuantumState |a> and DensityMatrix |b><b|, create a mixture state p|a><a| + q|b><b|
# You can also create a mixture states from two QuantumState or two DensitMatrix
a = QuantumState(2)
a.set_computational_basis(0b00)
b = DensityMatrix(2)
b.set_computational_basis(0b11)
p = 1 / 2
q = 1 / 2
c = make_mixture(p, a, q, b)
print(c.get_matrix())

Quantum gates

Types of quantum gate

Quantum gates are divided into two types: special gates and general gates. In Qulacs, quantum gates are not limited to unitary operators, and the operation of updating an arbitrary quantum state, such as Instrument and CPTP-map, is also called a gate.

Special gates are those that have a pre-specified gate matrix and can only perform limited deformations on quantum gates. For example, Pauli gate, rotation Pauli gate, projection measurement, etc. are supported. The advantage of a special gate is that the update function of the quantum state is more efficient than a general gate with limited properties. Also, at the time of definition, it holds information on whether or not it is diagonalized by each qubit at the basis of some Pauli, and this information is used for circuit optimization. The disadvantage of special gates is that the possible operations on the gates are limited for the reasons mentioned above.

A gate that has an explicit operation gate matrix is called a general gate. The advantage of general gates is that you can specify the gate matrix as you like, but the disadvantage is that the updates are slower than special gates.

Common operations for quantum gates

The gate matrix of the generated quantum gate can be obtained with the get_matrix function. Control qubits are not included in the gate matrix. In particular, be careful when obtain gates that do not have a gate matrix (for example, \(n\)-qubit Pauli rotating gates), which require a very large amount of memory and time. print function displays the gate information.

[2]:
import numpy as np
from qulacs.gate import X
gate = X(2)
mat = gate.get_matrix()
print(mat)
print(gate)
[[0.+0.j 1.+0.j]
 [1.+0.j 0.+0.j]]
 *** gate info ***
 * gate name : X
 * target    :
 2 : commute X
 * control   :
 * Pauli     : yes
 * Clifford  : yes
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

Special gate

The special gates are listed below.

1 qubit gate

Takes the index of the target bit as the first argument.

[10]:
from qulacs.gate import Identity # Identity matrix
from qulacs.gate import X, Y, Z     # Pauli
from qulacs.gate import H, S, Sdag, sqrtX, sqrtXdag, sqrtY, sqrtYdag # クリフォード
from qulacs.gate import T, Tdag # T gate
from qulacs.gate import P0, P1 # Projection to 0,1 (not normalized)
target = 3
gate = T(target)
print(gate)
 *** gate info ***
 * gate name : T
 * target    :
 3 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : yes
 * Parametric: no
 * Diagonal  : no

Identity does not update the quantum state, but when it is included into the quantum circuit, it is counted as a gate that consumes 1 step.

1 qubit rotating gate

Take the index of the target bit as the first argument and the rotation angle as the second argument.

[11]:
import numpy as np
from qulacs.gate import RX, RY, RZ
target = 0
angle = 0.1
gate = RX(target, angle)
print(gate)
print(gate.get_matrix())
 *** gate info ***
 * gate name : X-rotation
 * target    :
 0 : commute X
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

[[0.99875026+0.j         0.        +0.04997917j]
 [0.        +0.04997917j 0.99875026+0.j        ]]

The definition of rotating operation is \(R_X(\theta) = \exp(i\frac{\theta}{2} X)\)です。

IBMQ basis gate

IBMQ basis gate is a gate based on the virtual-Z decomposition defined by IBMQ’s OpenQASM.

[12]:
from qulacs.gate import U1,U2,U3
print(U3(0, 0.1, 0.2, 0.3))
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 0 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
            (0.99875,0) (-0.0477469,-0.0147699)
 (0.0489829,0.00992933)     (0.876486,0.478826)

Definitions are:

  • \(U_1(\lambda) = R_Z(\lambda)\)

  • \(U_2(\phi, \lambda) = R_Z(\phi+\frac{\pi}{2}) R_X(\frac{\pi}{2}) R_Z(\lambda-\frac{\pi}{2})\)

  • \(U_3(\theta, \phi, \lambda) = R_Z(\phi+3\pi) R_X(\pi/2) R_Z(\theta+\pi) R_X(\pi/2) R_Z(\lambda)\)

U3 matches the degree of freedom of any 1-qubit unitary operation.

2 qubit gate

Take the indexes of the target bit in the first and second arguments. The first argument of the CNOT gate is a control qubit. The remaining gates are symmetric operations.

[13]:
from qulacs.gate import CNOT, CZ, SWAP
control = 5
target = 2
target2 = 3
gate = CNOT(control, target)
print(gate)
gate = CZ(control, target)
gate = SWAP(target, target2)
 *** gate info ***
 * gate name : CNOT
 * target    :
 2 : commute X
 * control   :
 5 : value 1
 * Pauli     : no
 * Clifford  : yes
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

Multi-bit Pauli operation

Multi-bit Pauli operations define a gate with arguments as a list of target qubits and a list of Pauli operators. Since the update speed of an \(n\)-qubit Pauli operation has the same order as the update cost of a 1-qubit Pauli operation, Pauli’s tensor product should be defined as the gate in this form. In the Pauli operator specification, 1, 2, and 3 correspond to X, Y, and Z, respectively.

[14]:
from qulacs.gate import Pauli
target_list = [0,3,5]
pauli_index = [1,3,1] # 1:X , 2:Y, 3:Z
gate = Pauli(target_list, pauli_index) # = X_0 Z_3 X_5
print(gate)
print(gate.get_matrix())
 *** gate info ***
 * gate name : Pauli
 * target    :
 0 : commute X
 3 : commute     Z
 5 : commute X
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

[[ 0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  1.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j  1.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j -1.-0.j]
 [ 0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j -1.-0.j  0.+0.j]
 [ 0.+0.j  1.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 1.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j -1.-0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j -1.-0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j  0.+0.j]]
Multi-bit Pauli rotating operation

Multi-bit Pauli rotating operation rotates multi-bit Pauli operator. The multi-bit Pauli rotation becomes heavy calculation when the gate matrix is calculated greedily, but it can be updated efficiently if it is defined in this form.

[15]:
from qulacs.gate import PauliRotation
target_list = [0,3,5]
pauli_index = [1,3,1] # 1:X , 2:Y, 3:Z
angle = 0.5
gate = PauliRotation(target_list, pauli_index, angle) # = exp(i angle/2 X_0 Z_3 X_5)
print(gate)
print(gate.get_matrix().shape)
 *** gate info ***
 * gate name : Pauli-rotation
 * target    :
 0 : commute X
 3 : commute     Z
 5 : commute X
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

(8, 8)
Reversible circuit

Reversible circuit performs permutation operation between basis by giving a bijective function to a total number of \(2^n\) index. This is equivalent to the gate matrix being a permutation matrix. Please note that it will not work properly unless the given function is bijective.

[16]:
from qulacs.gate import ReversibleBoolean
def upper(val, dim):
    return (val+1)%dim
target_list = [0,1]
gate = ReversibleBoolean(target_list, upper)
print(gate)
state = QuantumState(3)
state.load(np.arange(2**3))
print(state.get_vector())
gate.update_quantum_state(state)
print(state.get_vector())
 *** gate info ***
 * gate name : ReversibleBoolean
 * target    :
 0 : commute
 1 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no

[0.+0.j 1.+0.j 2.+0.j 3.+0.j 4.+0.j 5.+0.j 6.+0.j 7.+0.j]
[3.+0.j 0.+0.j 1.+0.j 2.+0.j 7.+0.j 4.+0.j 5.+0.j 6.+0.j]

The above code moves the elements of the vector down one by one in the subspace of the qubit of interest (the bottom element moves to the top). ### State reflection This gate is \((I-2\ket{a}\bra{a})\), which is defined with the quantum state \(\ket{a}\) as an argument. This corresponds to the operation of reflecting based on the quantum state \(\ket{a}\). This gate appears in Grover search. The number of qubits on which this gate operates must match the number of qubits in the quantum state given as an argument.

[17]:
from qulacs.gate import StateReflection
from qulacs import QuantumState
axis = QuantumState(2)
axis.set_Haar_random_state(0)
state = QuantumState(2)
gate = StateReflection(axis)
gate.update_quantum_state(state)
print("axis", axis.get_vector())
print("reflected", state.get_vector())
gate.update_quantum_state(state)
print("two reflection", state.get_vector())
axis [0.26990561+0.18885571j 0.42520294-0.30443016j 0.33036863-0.07179331j
 0.02371619+0.70933j   ]
reflected [-0.78296897+0.j          0.11454257-0.32493882j  0.15121954-0.16353884j
  0.28072431+0.37394642j]
two reflection [ 1.00000000e+00-2.77555756e-17j -5.55111512e-17+0.00000000e+00j
 -2.77555756e-17+2.77555756e-17j  0.00000000e+00-1.11022302e-16j]
General gate

This is a quantum gate with a gate matrix.

Dense matrix gate

Gate defined based on a dense matrix.

[18]:
from qulacs.gate import DenseMatrix

# 1-qubit gate
gate = DenseMatrix(0, [[0,1],[1,0]])
print(gate)

# 2-qubit gate
gate = DenseMatrix([0,1], [[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]])
print(gate)
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 0 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(0,0) (1,0)
(1,0) (0,0)

 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 0 : commute
 1 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(1,0) (0,0) (0,0) (0,0)
(0,0) (1,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (1,0)
(0,0) (0,0) (1,0) (0,0)

Sparse matrix gate

A gate defined based on a sparse matrix. If the elements are sparse enough, they can be updated faster than a dense matrix. Define sparse matrices using scipy’s csc_matrix.

[20]:
from qulacs import QuantumState
from qulacs.gate import SparseMatrix
from scipy.sparse import csc_matrix
mat = csc_matrix((2,2))
mat[1,1] = 1
print("sparse matrix", mat)

gate = SparseMatrix([0], mat)
print(gate)

qs = QuantumState(2)
qs.load([1,2,3,4])
gate.update_quantum_state(qs)
print(qs.get_vector())
sparse matrix   (1, 1)  1.0
 *** gate info ***
 * gate name : SparseMatrix
 * target    :
 0 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
0 0
0 (1,0)


[0.+0.j 2.+0.j 0.+0.j 4.+0.j]
Add control bit

General gates can add a control qubit using the add_control_qubit function. You can also specify whether the target qubit has an effect when control qubit is 0 or 1.

[21]:
import numpy as np
from qulacs.gate import to_matrix_gate, X

index = 0
x_gate = X(index)
x_mat_gate = to_matrix_gate(x_gate)

# Operate only when 1st-qubit is 0
control_index = 1
control_with_value = 0
x_mat_gate.add_control_qubit(control_index, control_with_value)
print(x_mat_gate)

from qulacs import QuantumState
state = QuantumState(3)
state.load(np.arange(2**3))
print(state.get_vector())

x_mat_gate.update_quantum_state(state)
print(state.get_vector())
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 0 : commute X
 * control   :
 1 : value 0
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(0,0) (1,0)
(1,0) (0,0)

[0.+0.j 1.+0.j 2.+0.j 3.+0.j 4.+0.j 5.+0.j 6.+0.j 7.+0.j]
[1.+0.j 0.+0.j 2.+0.j 3.+0.j 5.+0.j 4.+0.j 6.+0.j 7.+0.j]

Operation to create a new gate from multiple gates

Gate product

Combine successively the operating quantum gates to create a new single quantum gate. This reduces access to quantum states.

[22]:
import numpy as np
from qulacs import QuantumState
from qulacs.gate import X, RY, merge

n = 3
state = QuantumState(n)
state.set_zero_state()

index = 1
x_gate = X(index)
angle = np.pi / 4.0
ry_gate = RY(index, angle)

# Create the new gate by combining gates
# The gate in the first augement is applied first
x_and_ry_gate = merge(x_gate, ry_gate)
print(x_and_ry_gate)
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 1 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
 (0.382683,0)   (0.92388,0)
  (0.92388,0) (-0.382683,0)

Gate sum

You can add multiple gates to create a new gate. This is useful for making the projection of the Pauli operator \(P\) onto the +1 eigenvalue space such as \((I + P) / 2\).

[23]:
import numpy as np
from qulacs.gate import P0,P1,add, merge, Identity, X, Z

gate00 = merge(P0(0),P0(1))
gate11 = merge(P1(0),P1(1))
# |00><00| + |11><11|
proj_00_or_11 = add(gate00, gate11)
print(proj_00_or_11)

gate_ii_zz = add(Identity(0), merge(Z(0),Z(1)))
gate_ii_xx = add(Identity(0), merge(X(0),X(1)))
proj_00_plus_11 = merge(gate_ii_zz, gate_ii_xx)
# ((|00>+|11>)(<00|+<11|))/2 = (II + ZZ)(II + XX)/4
proj_00_plus_11.multiply_scalar(0.25)
print(proj_00_plus_11)
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 0 : commute
 1 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(1,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (0,0)
(0,0) (0,0) (0,0) (1,0)

 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 0 : commute
 1 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
(0.5,0)   (0,0)   (0,0) (0.5,0)
  (0,0)   (0,0)   (0,0)   (0,0)
  (0,0)   (0,0)   (0,0)   (0,0)
(0.5,0)   (0,0)   (0,0) (0.5,0)

Random unitary

Use the RandomUnitary function to sample a random unitary matrix with the Haar measure and generate a dense matrix gate.

[24]:
from qulacs.gate import RandomUnitary
target_list = [2,3]
gate = RandomUnitary(target_list)
print(gate)
 *** gate info ***
 * gate name : DenseMatrix
 * target    :
 2 : commute
 3 : commute
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : no
 * Matrix
 (-0.549679,-0.199309)    (-0.41282,0.191987)  (-0.430215,-0.393607)  (-0.152234,-0.296078)
   (0.255527,0.290869)   (0.136685,-0.154401)  (0.0998426,-0.553577) (-0.700763,-0.0097331)
   (0.056699,0.690511) (-0.488394,-0.0743973)  (0.0480177,-0.260356)    (0.439362,0.113074)
 (0.156442,-0.0611172)  (-0.695389,-0.150231)    (0.177095,0.492055) (-0.433419,-0.0657552)

Stochastic operation

Using the Probabilistic function, create the stochastic operation by giving multiple gate operations and probability distribution. If the sum of the given probability distributions is less than 1, Identity will operate with a probability less than 1.

[25]:
from qulacs.gate import Probabilistic, H, Z
distribution = [0.2, 0.2, 0.2]
gate_list = [H(0), Z(0), X(1)]
gate = Probabilistic(distribution, gate_list)
print(gate)

from qulacs import QuantumState
state = QuantumState(2)
for _ in range(10):
    gate.update_quantum_state(state)
    print(state.get_vector())
 *** gate info ***
 * gate name : Generic gate
 * target    :
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : yes

[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[ 0.+0.j -0.-0.j  1.+0.j -0.-0.j]
[0.        +0.j 0.        +0.j 0.70710678+0.j 0.70710678+0.j]
[0.        +0.j 0.        +0.j 0.70710678+0.j 0.70710678+0.j]
[ 0.        +0.j -0.        -0.j  0.70710678+0.j -0.70710678-0.j]
[ 0.70710678+0.j -0.70710678-0.j  0.        +0.j -0.        -0.j]
[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
[ 0.+0.j -1.-0.j  0.+0.j -0.-0.j]

BitFlipNoise, DephasingNoise, IndependentXZNoise, DepolarizingNoise, and TwoQubitDepolarizingNoise gates are defined as stochastic gates. Probabilistic instances are generated by entering the error probabilities.

[26]:
from qulacs.gate import BitFlipNoise, DephasingNoise, IndependentXZNoise, DepolarizingNoise, TwoQubitDepolarizingNoise
target = 0
second_target = 1
error_prob = 0.8
gate = BitFlipNoise(target, error_prob) # X: prob
gate = DephasingNoise(target, error_prob) # Z: prob
gate = IndependentXZNoise(target, error_prob) # X,Z : prob*(1-prob), Y: prob*prob
gate = DepolarizingNoise(target, error_prob) # X,Y,Z : prob/3
gate = TwoQubitDepolarizingNoise(target, second_target, error_prob) # {I,X,Y,Z} \times {I,X,Y,Z} \setminus {II} : prob/15

from qulacs import QuantumState
state = QuantumState(2)
for _ in range(10):
    gate.update_quantum_state(state)
    print(state.get_vector())
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
[0.-0.j 0.+1.j 0.-0.j 0.+0.j]
[0.-0.j 0.+1.j 0.-0.j 0.+0.j]
[ 0.-0.j -0.-1.j  0.-0.j -0.-0.j]
[0.+0.j 0.-0.j 0.+0.j 0.-1.j]
[0.+0.j 0.-0.j 0.+0.j 0.-1.j]
[-1.+0.j  0.+0.j -0.+0.j  0.+0.j]
[ 0.-0.j  0.+0.j  0.+0.j -0.-1.j]
[ 0.-0.j  0.+0.j  0.+0.j -0.-1.j]
[ 0.-0.j  0.+0.j  0.+0.j -0.-1.j]
Noisy evolution

There are two gates, NoisyEvolution and NoisyEvolution_fast, that interact from the environment and are attenuated by time evolution. They can be used by the following steps

  1. set up the system to be interacted with by the environment as a Hamiltonian and specify the operator of the interaction.

  2. specify the value to be evolved in time and the time to be varied microscopically.

  3. solve the differential equation.

    • NoisyEvolution solves differential equations using Runge-Kutta method.

    • NoisyEvolution_fast extracts a matrix and finds it by diagonalization.

It is recommended to use NoisyEvolution_fast because NoisyEvolution_fast does not require specifying the time to make a small change and it is fast.

[3]:
from qulacs import QuantumState, Observable, GeneralQuantumOperator
from qulacs.gate import NoisyEvolution, NoisyEvolution_fast, H

n = 2
observable = Observable(n)
observable.add_operator(1., "X 0")

# create hamiltonian and collapse operator
hamiltonian = Observable(n)
hamiltonian.add_operator(1., "Z 0 Z 1")

decay_rate_z = 0.2
decay_rate_p = 0.6
decay_rate_m = 0.1

# interacting operator
c_ops = [GeneralQuantumOperator(n) for _ in range(3*n)]
c_ops[0].add_operator(decay_rate_z, "Z 0")
c_ops[1].add_operator(decay_rate_z, "Z 1")
c_ops[2].add_operator(decay_rate_p/2, "X 0")
c_ops[2].add_operator(decay_rate_p/2*1j, "Y 0")
c_ops[3].add_operator(decay_rate_p/2, "X 1")
c_ops[3].add_operator(decay_rate_p/2*1j, "Y 1")
c_ops[4].add_operator(decay_rate_m/2, "X 0")
c_ops[4].add_operator(-decay_rate_m/2*1j, "Y 0")
c_ops[5].add_operator(decay_rate_m/2, "X 1")
c_ops[5].add_operator(-decay_rate_m/2*1j, "Y 1")

time = 2.
gate = NoisyEvolution_fast(hamiltonian, c_ops, time)
#dt = .1
#gate = NoisyEvolution(hamiltonian, c_ops, time, dt)

exp = 0.
n_samples = 1000
state = QuantumState(n)
for k in range(n_samples):
   state.set_zero_state()
   H(0).update_quantum_state(state)
   H(1).update_quantum_state(state)
   gate.update_quantum_state(state)
   exp += observable.get_expectation_value(state) / n_samples
   print(f"[{k}] exp: {exp}")
[0] exp: -0.0006155544536970823
[1] exp: -0.0006155544536970823
[2] exp: 0.00028465213360111513
[3] exp: -0.0003309023200959672
[4] exp: -0.0009464567737930495
[5] exp: -0.0009464567737930495
[6] exp: -0.0009464567737930495
[7] exp: -0.0009464567737930495
[8] exp: -0.0009464567737930495
[9] exp: -0.0015620112274901319
[10] exp: -0.0022830973241566837
[11] exp: -0.0022830973241566837
[12] exp: -0.0022830973241566837
[13] exp: -0.002898651777853766
[14] exp: -0.002898651777853766
[15] exp: -0.0035142062315508486
[16] exp: -0.0035142062315508486
[17] exp: -0.004129760685247931
[18] exp: -0.004129760685247931
[19] exp: -0.004745315138945013
[20] exp: -0.004745315138945013
[21] exp: -0.004745315138945013
[22] exp: -0.005360869592642096
[23] exp: -0.005976424046339178
[24] exp: -0.006591978500036261
[25] exp: -0.006591978500036261
[26] exp: -0.006591978500036261
[27] exp: -0.007207532953733343
[28] exp: -0.007823087407430426
[29] exp: -0.007823087407430426
[30] exp: -0.008438641861127508
[31] exp: -0.008438641861127508
[32] exp: -0.00905419631482459
[33] exp: -0.008646834619727773
[34] exp: -0.009262389073424856
[35] exp: -0.009877943527121938
[36] exp: -0.01049349798081902
[37] exp: -0.011419090630198456
[38] exp: -0.012034645083895538
[39] exp: -0.01265019953759262
[40] exp: -0.01265019953759262
[41] exp: -0.01265019953759262
[42] exp: -0.013265753991289703
[43] exp: -0.013692461721774537
[44] exp: -0.01434682754881815
[45] exp: -0.01434682754881815
[46] exp: -0.014962382002515233
[47] exp: -0.014962382002515233
[48] exp: -0.015577936456212315
[49] exp: -0.015577936456212315
[50] exp: -0.016193490909909396
[51] exp: -0.016809045363606476
[52] exp: -0.017424599817303557
[53] exp: -0.018040154271000638
[54] exp: -0.01865570872469772
[55] exp: -0.0192712631783948
[56] exp: -0.01988681763209188
[57] exp: -0.02050237208578896
[58] exp: -0.02111792653948604
[59] exp: -0.022007366313092046
[60] exp: -0.022007366313092046
[61] exp: -0.02139181185939496
[62] exp: -0.022007366313092042
[63] exp: -0.022007366313092042
[64] exp: -0.022622920766789123
[65] exp: -0.021856515255194026
[66] exp: -0.022472069708891106
[67] exp: -0.021856515255194026
[68] exp: -0.022472069708891106
[69] exp: -0.02154025585060333
[70] exp: -0.02215581030430041
[71] exp: -0.02277136475799749
[72] exp: -0.02215581030430041
[73] exp: -0.02154025585060333
[74] exp: -0.02154025585060333
[75] exp: -0.02154025585060333
[76] exp: -0.020924701396906248
[77] exp: -0.02027348570580591
[78] exp: -0.020889040159502992
[79] exp: -0.020889040159502992
[80] exp: -0.021504594613200072
[81] exp: -0.021504594613200072
[82] exp: -0.020889040159502992
[83] exp: -0.021504594613200072
[84] exp: -0.022120149066897153
[85] exp: -0.022120149066897153
[86] exp: -0.021243892746641374
[87] exp: -0.021243892746641374
[88] exp: -0.021243892746641374
[89] exp: -0.021243892746641374
[90] exp: -0.022185495290800217
[91] exp: -0.022801049744497297
[92] exp: -0.023416604198194378
[93] exp: -0.02403215865189146
[94] exp: -0.024774427325995912
[95] exp: -0.025389981779692993
[96] exp: -0.024616313200662678
[97] exp: -0.02523186765435976
[98] exp: -0.02584742210805684
[99] exp: -0.02584742210805684
[100] exp: -0.02584742210805684
[101] exp: -0.02646297656175392
[102] exp: -0.027078531015451
[103] exp: -0.02646297656175392
[104] exp: -0.02738285481457356
[105] exp: -0.02799840926827064
[106] exp: -0.02861396372196772
[107] exp: -0.0292295181756648
[108] exp: -0.02861396372196772
[109] exp: -0.0292295181756648
[110] exp: -0.0292295181756648
[111] exp: -0.028844127085841716
[112] exp: -0.029459681539538797
[113] exp: -0.030075235993235878
[114] exp: -0.03069079044693296
[115] exp: -0.03130634490063004
[116] exp: -0.03192189935432713
[117] exp: -0.03253745380802421
[118] exp: -0.033153008261721295
[119] exp: -0.033153008261721295
[120] exp: -0.03256731390197995
[121] exp: -0.031697881936676685
[122] exp: -0.0326262076677459
[123] exp: -0.0326262076677459
[124] exp: -0.03324176212144298
[125] exp: -0.03329003790769807
[126] exp: -0.03329003790769807
[127] exp: -0.033178062110633705
[128] exp: -0.033178062110633705
[129] exp: -0.03379361656433079
[130] exp: -0.03469337345856942
[131] exp: -0.0353089279122665
[132] exp: -0.035274712648132055
[133] exp: -0.03457582550242758
[134] exp: -0.03519137995612467
[135] exp: -0.03519137995612467
[136] exp: -0.03548433926214502
[137] exp: -0.0360998937158421
[138] exp: -0.036715448169539186
[139] exp: -0.03764651733823437
[140] exp: -0.03799390757259266
[141] exp: -0.03735273794352331
[142] exp: -0.037968292397220396
[143] exp: -0.03858384685091748
[144] exp: -0.039199401304614565
[145] exp: -0.03981495575831165
[146] exp: -0.04043051021200873
[147] exp: -0.04104606466570582
[148] exp: -0.040898738600438696
[149] exp: -0.04151429305413578
[150] exp: -0.042389071112415314
[151] exp: -0.0430046255661124
[152] exp: -0.04362018001980948
[153] exp: -0.044235734473506566
[154] exp: -0.04485128892720365
[155] exp: -0.045466843380900734
[156] exp: -0.04632420363925691
[157] exp: -0.046939758092954
[158] exp: -0.046939758092954
[159] exp: -0.046939758092954
[160] exp: -0.04755531254665108
[161] exp: -0.047945530209456085
[162] exp: -0.04856108466315317
[163] exp: -0.04917663911685025
[164] exp: -0.04979219357054734
[165] exp: -0.05040774802424442
[166] exp: -0.05096822096932116
[167] exp: -0.05096822096932116
[168] exp: -0.05096822096932116
[169] exp: -0.05096822096932116
[170] exp: -0.05070501056763049
[171] exp: -0.05028426867636907
[172] exp: -0.04966871422267199
[173] exp: -0.05028426867636907
[174] exp: -0.049786289569978874
[175] exp: -0.05040184402367596
[176] exp: -0.05018326709830215
[177] exp: -0.05079882155199923
[178] exp: -0.05079882155199923
[179] exp: -0.051414376005696316
[180] exp: -0.0520299304593934
[181] exp: -0.0520299304593934
[182] exp: -0.05244870743096235
[183] exp: -0.05332093018234459
[184] exp: -0.05255129095555087
[185] exp: -0.053406234553578354
[186] exp: -0.053406234553578354
[187] exp: -0.053406234553578354
[188] exp: -0.053406234553578354
[189] exp: -0.05402178900727544
[190] exp: -0.05402178900727544
[191] exp: -0.05463734346097252
[192] exp: -0.05463734346097252
[193] exp: -0.055252897914669606
[194] exp: -0.05586845236836669
[195] exp: -0.05586845236836669
[196] exp: -0.05586845236836669
[197] exp: -0.05586845236836669
[198] exp: -0.056484006822063774
[199] exp: -0.05709956127576086
[200] exp: -0.05771511572945794
[201] exp: -0.057257331940338795
[202] exp: -0.05787288639403588
[203] exp: -0.05848844084773296
[204] exp: -0.05848844084773296
[205] exp: -0.05848844084773296
[206] exp: -0.05910399530143005
[207] exp: -0.05971954975512713
[208] exp: -0.060335104208824215
[209] exp: -0.0609506586625213
[210] exp: -0.061566213116218384
[211] exp: -0.06218176756991547
[212] exp: -0.061566213116218384
[213] exp: -0.061566213116218384
[214] exp: -0.061566213116218384
[215] exp: -0.06218176756991547
[216] exp: -0.06279732202361255
[217] exp: -0.06341287647730963
[218] exp: -0.06341287647730963
[219] exp: -0.06320242027713613
[220] exp: -0.06381797473083321
[221] exp: -0.06381797473083321
[222] exp: -0.06381797473083321
[223] exp: -0.0644335291845303
[224] exp: -0.0644335291845303
[225] exp: -0.0644335291845303
[226] exp: -0.06504908363822738
[227] exp: -0.06566045904518757
[228] exp: -0.06629484601530813
[229] exp: -0.06691040046900522
[230] exp: -0.0675259549227023
[231] exp: -0.0675259549227023
[232] exp: -0.0675259549227023
[233] exp: -0.06814150937639939
[234] exp: -0.0675259549227023
[235] exp: -0.0675259549227023
[236] exp: -0.06658499178537876
[237] exp: -0.06720054623907584
[238] exp: -0.06781610069277293
[239] exp: -0.06843165514647001
[240] exp: -0.06763770681196025
[241] exp: -0.06763770681196025
[242] exp: -0.06825326126565734
[243] exp: -0.06763770681196025
[244] exp: -0.06853694568164893
[245] exp: -0.06915250013534602
[246] exp: -0.0697680545890431
[247] exp: -0.0697680545890431
[248] exp: -0.07038360904274019
[249] exp: -0.07099916349643727
[250] exp: -0.07161471795013435
[251] exp: -0.07161471795013435
[252] exp: -0.07223027240383144
[253] exp: -0.07284582685752852
[254] exp: -0.07346138131122561
[255] exp: -0.07284582685752852
[256] exp: -0.07366915832301378
[257] exp: -0.07428471277671087
[258] exp: -0.07428471277671087
[259] exp: -0.07490026723040795
[260] exp: -0.07551582168410503
[261] exp: -0.07645485198073491
[262] exp: -0.077013721174219
[263] exp: -0.07639816672052191
[264] exp: -0.07565678898420304
[265] exp: -0.07565678898420304
[266] exp: -0.07565678898420304
[267] exp: -0.07626129807519072
[268] exp: -0.0768768525288878
[269] exp: -0.0768768525288878
[270] exp: -0.0768768525288878
[271] exp: -0.07749240698258489
[272] exp: -0.07831312700969287
[273] exp: -0.07831312700969287
[274] exp: -0.07892868146338995
[275] exp: -0.07954423591708704
[276] exp: -0.07954423591708704
[277] exp: -0.08015979037078412
[278] exp: -0.08059094536032106
[279] exp: -0.08059094536032106
[280] exp: -0.08120649981401815
[281] exp: -0.08157819624890524
[282] exp: -0.08219375070260232
[283] exp: -0.0828093051562994
[284] exp: -0.0828093051562994
[285] exp: -0.08342485960999649
[286] exp: -0.08404041406369357
[287] exp: -0.08404041406369357
[288] exp: -0.08465596851739066
[289] exp: -0.08527152297108774
[290] exp: -0.08527152297108774
[291] exp: -0.08527152297108774
[292] exp: -0.08527152297108774
[293] exp: -0.08588707742478482
[294] exp: -0.0867567128540497
[295] exp: -0.0867567128540497
[296] exp: -0.08769186862224454
[297] exp: -0.08830742307594162
[298] exp: -0.08762675616137959
[299] exp: -0.08824231061507667
[300] exp: -0.08885786506877376
[301] exp: -0.08947341952247084
[302] exp: -0.09008897397616793
[303] exp: -0.08992489440956956
[304] exp: -0.09054044886326665
[305] exp: -0.09115600331696373
[306] exp: -0.09115600331696373
[307] exp: -0.09177155777066082
[308] exp: -0.0923871122243579
[309] exp: -0.09300266667805498
[310] exp: -0.09300266667805498
[311] exp: -0.09361822113175207
[312] exp: -0.09362259542014313
[313] exp: -0.0927733626660045
[314] exp: -0.09338891711970158
[315] exp: -0.09400447157339867
[316] exp: -0.09400447157339867
[317] exp: -0.09400447157339867
[318] exp: -0.09462002602709575
[319] exp: -0.09523558048079284
[320] exp: -0.09466317228765633
[321] exp: -0.09527872674135342
[322] exp: -0.0958942811950505
[323] exp: -0.0958942811950505
[324] exp: -0.09650983564874759
[325] exp: -0.09712539010244467
[326] exp: -0.09712539010244467
[327] exp: -0.09774094455614175
[328] exp: -0.09835649900983884
[329] exp: -0.09835649900983884
[330] exp: -0.09897205346353592
[331] exp: -0.09985418221730988
[332] exp: -0.10046973667100696
[333] exp: -0.09995536553146189
[334] exp: -0.10028784636961895
[335] exp: -0.10090340082331603
[336] exp: -0.10090340082331603
[337] exp: -0.10090340082331603
[338] exp: -0.10151895527701311
[339] exp: -0.10151895527701311
[340] exp: -0.10156128221918276
[341] exp: -0.10217683667287984
[342] exp: -0.10217683667287984
[343] exp: -0.10279239112657693
[344] exp: -0.10340794558027401
[345] exp: -0.10340794558027401
[346] exp: -0.10340794558027401
[347] exp: -0.1040235000339711
[348] exp: -0.1040235000339711
[349] exp: -0.1040235000339711
[350] exp: -0.10372845672845833
[351] exp: -0.10372845672845833
[352] exp: -0.10449360452292311
[353] exp: -0.10449360452292311
[354] exp: -0.10365886584907227
[355] exp: -0.10427442030276936
[356] exp: -0.10350990238566947
[357] exp: -0.10412545683936655
[358] exp: -0.10474101129306364
[359] exp: -0.10412545683936655
[360] exp: -0.10474101129306364
[361] exp: -0.10535656574676072
[362] exp: -0.1059721202004578
[363] exp: -0.1059721202004578
[364] exp: -0.10658767465415489
[365] exp: -0.10720322910785197
[366] exp: -0.10781878356154906
[367] exp: -0.10720322910785197
[368] exp: -0.10781878356154906
[369] exp: -0.10843433801524614
[370] exp: -0.10937599813535294
[371] exp: -0.1103166763434265
[372] exp: -0.11038340107086211
[373] exp: -0.11038340107086211
[374] exp: -0.1109989555245592
[375] exp: -0.11161450997825628
[376] exp: -0.11223006443195337
[377] exp: -0.11220202348282973
[378] exp: -0.11281757793652682
[379] exp: -0.11220202348282973
[380] exp: -0.11281757793652682
[381] exp: -0.11281757793652682
[382] exp: -0.1134331323902239
[383] exp: -0.11404868684392098
[384] exp: -0.11466424129761807
[385] exp: -0.11382570392058199
[386] exp: -0.11444125837427907
[387] exp: -0.11520844342214584
[388] exp: -0.11520844342214584
[389] exp: -0.11599975787962051
[390] exp: -0.1166153123333176
[391] exp: -0.1166153123333176
[392] exp: -0.11754910433681005
[393] exp: -0.11754910433681005
[394] exp: -0.11816465879050714
[395] exp: -0.11729727862856759
[396] exp: -0.11791283308226468
[397] exp: -0.11852838753596176
[398] exp: -0.11851878407068736
[399] exp: -0.11851878407068736
[400] exp: -0.11913433852438444
[401] exp: -0.12004965856631672
[402] exp: -0.11942412855813303
[403] exp: -0.11942412855813303
[404] exp: -0.12003968301183011
[405] exp: -0.12089213649740388
[406] exp: -0.12150769095110096
[407] exp: -0.12150769095110096
[408] exp: -0.12089213649740388
[409] exp: -0.12150769095110096
[410] exp: -0.12212324540479805
[411] exp: -0.12273879985849513
[412] exp: -0.12335435431219222
[413] exp: -0.12273879985849513
[414] exp: -0.12273879985849513
[415] exp: -0.12335435431219222
[416] exp: -0.1239699087658893
[417] exp: -0.12458546321958638
[418] exp: -0.12550893711564767
[419] exp: -0.12612449156934474
[420] exp: -0.1267400460230418
[421] exp: -0.12735560047673888
[422] exp: -0.12801527002970922
[423] exp: -0.1286308244834063
[424] exp: -0.12801527002970922
[425] exp: -0.12801527002970922
[426] exp: -0.12866152456840213
[427] exp: -0.1292770790220992
[428] exp: -0.1283833689492389
[429] exp: -0.12922282598498694
[430] exp: -0.12922282598498694
[431] exp: -0.12922282598498694
[432] exp: -0.129838380438684
[433] exp: -0.12915689756143836
[434] exp: -0.12977245201513543
[435] exp: -0.1303880064688325
[436] exp: -0.13100356092252957
[437] exp: -0.13161911537622664
[438] exp: -0.13161911537622664
[439] exp: -0.1322346698299237
[440] exp: -0.1322346698299237
[441] exp: -0.1322346698299237
[442] exp: -0.13285022428362078
[443] exp: -0.13240052676667394
[444] exp: -0.133016081220371
[445] exp: -0.13240052676667394
[446] exp: -0.133016081220371
[447] exp: -0.13363163567406808
[448] exp: -0.13424719012776515
[449] exp: -0.13424719012776515
[450] exp: -0.13486274458146222
[451] exp: -0.1354782990351593
[452] exp: -0.1355789395032875
[453] exp: -0.1355789395032875
[454] exp: -0.13619449395698457
[455] exp: -0.13681004841068165
[456] exp: -0.13681004841068165
[457] exp: -0.13742560286437872
[458] exp: -0.13804115731807579
[459] exp: -0.13865671177177286
[460] exp: -0.13804115731807579
[461] exp: -0.13804115731807579
[462] exp: -0.13804115731807579
[463] exp: -0.13836275404663967
[464] exp: -0.13897830850033674
[465] exp: -0.13836275404663967
[466] exp: -0.13906106231693482
[467] exp: -0.13906106231693482
[468] exp: -0.13999196215156873
[469] exp: -0.13937640769787166
[470] exp: -0.13999196215156873
[471] exp: -0.1406075166052658
[472] exp: -0.1406075166052658
[473] exp: -0.1406075166052658
[474] exp: -0.1406075166052658
[475] exp: -0.14122307105896287
[476] exp: -0.14183862551265994
[477] exp: -0.14183862551265994
[478] exp: -0.142454179966357
[479] exp: -0.142454179966357
[480] exp: -0.14306973442005408
[481] exp: -0.14368528887375115
[482] exp: -0.14430084332744822
[483] exp: -0.14430084332744822
[484] exp: -0.1451826007693763
[485] exp: -0.14579815522307338
[486] exp: -0.14579815522307338
[487] exp: -0.14641370967677045
[488] exp: -0.14702926413046752
[489] exp: -0.1476448185841646
[490] exp: -0.1476448185841646
[491] exp: -0.14828957592651873
[492] exp: -0.1489051303802158
[493] exp: -0.1489051303802158
[494] exp: -0.14952068483391287
[495] exp: -0.15013623928760994
[496] exp: -0.150751793741307
[497] exp: -0.15136734819500408
[498] exp: -0.15136734819500408
[499] exp: -0.15198290264870115
[500] exp: -0.15259845710239822
[501] exp: -0.15342576279459505
[502] exp: -0.1527157862429297
[503] exp: -0.15333134069662677
[504] exp: -0.15400963967833595
[505] exp: -0.15462519413203302
[506] exp: -0.1552407485857301
[507] exp: -0.15609221841700868
[508] exp: -0.15609221841700868
[509] exp: -0.15670777287070575
[510] exp: -0.15756360783863435
[511] exp: -0.15817916229233142
[512] exp: -0.1587947167460285
[513] exp: -0.15941027119972556
[514] exp: -0.1603515042602213
[515] exp: -0.16096705871391837
[516] exp: -0.16096705871391837
[517] exp: -0.16096705871391837
[518] exp: -0.16096705871391837
[519] exp: -0.16096705871391837
[520] exp: -0.16158261316761544
[521] exp: -0.1621981676213125
[522] exp: -0.16281372207500958
[523] exp: -0.16373090678339808
[524] exp: -0.16283280712951734
[525] exp: -0.1634483615832144
[526] exp: -0.16283280712951734
[527] exp: -0.1634483615832144
[528] exp: -0.16406391603691148
[529] exp: -0.16467947049060855
[530] exp: -0.1644017050894879
[531] exp: -0.1644017050894879
[532] exp: -0.1644017050894879
[533] exp: -0.16377946085970288
[534] exp: -0.16439501531339995
[535] exp: -0.16377946085970288
[536] exp: -0.16439501531339995
[537] exp: -0.16439501531339995
[538] exp: -0.16501056976709702
[539] exp: -0.1656261242207941
[540] exp: -0.16624167867449116
[541] exp: -0.16685723312818823
[542] exp: -0.1674727875818853
[543] exp: -0.1674727875818853
[544] exp: -0.16808834203558237
[545] exp: -0.16870389648927944
[546] exp: -0.1693194509429765
[547] exp: -0.16993500539667358
[548] exp: -0.16993500539667358
[549] exp: -0.17055055985037065
[550] exp: -0.17116611430406772
[551] exp: -0.17144413665008618
[552] exp: -0.17205969110378325
[553] exp: -0.17267524555748032
[554] exp: -0.1732908000111774
[555] exp: -0.17340554640099856
[556] exp: -0.17402110085469563
[557] exp: -0.17364917907930433
[558] exp: -0.17364917907930433
[559] exp: -0.17270769519848728
[560] exp: -0.17332324965218435
[561] exp: -0.17393880410588142
[562] exp: -0.1745543585595785
[563] exp: -0.1745543585595785
[564] exp: -0.17516991301327556
[565] exp: -0.17516991301327556
[566] exp: -0.17578546746697263
[567] exp: -0.1764010219206697
[568] exp: -0.17701657637436677
[569] exp: -0.17767756727117226
[570] exp: -0.17829312172486933
[571] exp: -0.1789086761785664
[572] exp: -0.17952423063226347
[573] exp: -0.18013978508596054
[574] exp: -0.1804705539298588
[575] exp: -0.17973981678169074
[576] exp: -0.17973981678169074
[577] exp: -0.1803553712353878
[578] exp: -0.18097092568908488
[579] exp: -0.1803553712353878
[580] exp: -0.1803553712353878
[581] exp: -0.1803553712353878
[582] exp: -0.18097092568908488
[583] exp: -0.18097092568908488
[584] exp: -0.18158648014278195
[585] exp: -0.18158648014278195
[586] exp: -0.18097092568908488
[587] exp: -0.18158648014278195
[588] exp: -0.18097092568908488
[589] exp: -0.18097092568908488
[590] exp: -0.18158648014278195
[591] exp: -0.18220203459647902
[592] exp: -0.1828175890501761
[593] exp: -0.1828175890501761
[594] exp: -0.1820724559922206
[595] exp: -0.1820724559922206
[596] exp: -0.18268801044591768
[597] exp: -0.18330356489961475
[598] exp: -0.18391911935331182
[599] exp: -0.18391911935331182
[600] exp: -0.18330356489961475
[601] exp: -0.18391911935331182
[602] exp: -0.1845346738070089
[603] exp: -0.18515022826070596
[604] exp: -0.18515022826070596
[605] exp: -0.18515022826070596
[606] exp: -0.18515022826070596
[607] exp: -0.18606380694628738
[608] exp: -0.18655856768528278
[609] exp: -0.18655856768528278
[610] exp: -0.18743839411350321
[611] exp: -0.18819919063543192
[612] exp: -0.188814745089129
[613] exp: -0.18943029954282606
[614] exp: -0.18943029954282606
[615] exp: -0.19004585399652313
[616] exp: -0.19004585399652313
[617] exp: -0.19097182613698546
[618] exp: -0.19073563167538965
[619] exp: -0.19135118612908672
[620] exp: -0.19150988368625607
[621] exp: -0.19212543813995314
[622] exp: -0.19249690955466886
[623] exp: -0.19212397847611082
[624] exp: -0.1927395329298079
[625] exp: -0.1927395329298079
[626] exp: -0.19335508738350496
[627] exp: -0.19335508738350496
[628] exp: -0.19358784467544485
[629] exp: -0.19420339912914192
[630] exp: -0.19420339912914192
[631] exp: -0.194818953582839
[632] exp: -0.19543450803653606
[633] exp: -0.19543450803653606
[634] exp: -0.19605006249023313
[635] exp: -0.19605006249023313
[636] exp: -0.19605006249023313
[637] exp: -0.19659884679466627
[638] exp: -0.19721440124836334
[639] exp: -0.1978299557020604
[640] exp: -0.19844551015575748
[641] exp: -0.19906106460945455
[642] exp: -0.19967661906315162
[643] exp: -0.2002921735168487
[644] exp: -0.20090772797054576
[645] exp: -0.20152328242424283
[646] exp: -0.2021388368779399
[647] exp: -0.2021388368779399
[648] exp: -0.2021388368779399
[649] exp: -0.2021388368779399
[650] exp: -0.2021388368779399
[651] exp: -0.2021388368779399
[652] exp: -0.2021388368779399
[653] exp: -0.20275439133163697
[654] exp: -0.20336994578533404
[655] exp: -0.20398550023903111
[656] exp: -0.20398550023903111
[657] exp: -0.20460105469272818
[658] exp: -0.20521660914642526
[659] exp: -0.20608586916399166
[660] exp: -0.20670142361768873
[661] exp: -0.2073169780713858
[662] exp: -0.20670142361768873
[663] exp: -0.2074788621088741
[664] exp: -0.20809441656257116
[665] exp: -0.20870997101626823
[666] exp: -0.2093255254699653
[667] exp: -0.2093255254699653
[668] exp: -0.2093255254699653
[669] exp: -0.20994107992366237
[670] exp: -0.21055663437735944
[671] exp: -0.2111721888310565
[672] exp: -0.21196939145049798
[673] exp: -0.21258494590419505
[674] exp: -0.21320050035789212
[675] exp: -0.21383806905960145
[676] exp: -0.21445362351329852
[677] exp: -0.21383806905960145
[678] exp: -0.21290012410261003
[679] exp: -0.2135156785563071
[680] exp: -0.2135156785563071
[681] exp: -0.21413123301000417
[682] exp: -0.2135156785563071
[683] exp: -0.21413123301000417
[684] exp: -0.21413123301000417
[685] exp: -0.21474678746370124
[686] exp: -0.21474678746370124
[687] exp: -0.21474678746370124
[688] exp: -0.2153623419173983
[689] exp: -0.21597789637109538
[690] exp: -0.2150429143742402
[691] exp: -0.21565846882793727
[692] exp: -0.21551390800633224
[693] exp: -0.21551390800633224
[694] exp: -0.21551390800633224
[695] exp: -0.21551390800633224
[696] exp: -0.21612946246002931
[697] exp: -0.21551390800633224
[698] exp: -0.21612946246002931
[699] exp: -0.21612946246002931
[700] exp: -0.21674501691372638
[701] exp: -0.21674501691372638
[702] exp: -0.21763149675266333
[703] exp: -0.21763149675266333
[704] exp: -0.21844270576049665
[705] exp: -0.21782715130679958
[706] exp: -0.21844270576049665
[707] exp: -0.21905826021419372
[708] exp: -0.21905826021419372
[709] exp: -0.2196738146678908
[710] exp: -0.22028936912158786
[711] exp: -0.22090492357528493
[712] exp: -0.22090492357528493
[713] exp: -0.22182850664546006
[714] exp: -0.2214704732413619
[715] exp: -0.22208602769505897
[716] exp: -0.22270158214875604
[717] exp: -0.22331713660245311
[718] exp: -0.22393269105615018
[719] exp: -0.22454824550984726
[720] exp: -0.22516379996354433
[721] exp: -0.22471567931191222
[722] exp: -0.2253312337656093
[723] exp: -0.22594678821930636
[724] exp: -0.22656234267300343
[725] exp: -0.22656234267300343
[726] exp: -0.22563124834934478
[727] exp: -0.22624680280304185
[728] exp: -0.22695221209638056
[729] exp: -0.22756776655007763
[730] exp: -0.2281833210037747
[731] exp: -0.22879887545747177
[732] exp: -0.22791825864325793
[733] exp: -0.22791825864325793
[734] exp: -0.22791825864325793
[735] exp: -0.228533813096955
[736] exp: -0.22914936755065207
[737] exp: -0.22976492200434914
[738] exp: -0.22976492200434914
[739] exp: -0.23006736939645864
[740] exp: -0.23006736939645864
[741] exp: -0.2306829238501557
[742] exp: -0.23129847830385278
[743] exp: -0.23191403275754985
[744] exp: -0.23269331572343316
[745] exp: -0.23229780870770897
[746] exp: -0.23291336316140604
[747] exp: -0.2335289176151031
[748] exp: -0.2335289176151031
[749] exp: -0.23414447206880018
[750] exp: -0.23476002652249725
[751] exp: -0.23537558097619432
[752] exp: -0.2359911354298914
[753] exp: -0.2366816862279394
[754] exp: -0.23729724068163646
[755] exp: -0.2366816862279394
[756] exp: -0.23729724068163646
[757] exp: -0.2366816862279394
[758] exp: -0.23729724068163646
[759] exp: -0.23751966337302066
[760] exp: -0.23813521782671773
[761] exp: -0.23813521782671773
[762] exp: -0.23751966337302066
[763] exp: -0.23748434234037025
[764] exp: -0.23809989679406732
[765] exp: -0.2387154512477644
[766] exp: -0.23933100570146146
[767] exp: -0.23994656015515853
[768] exp: -0.2405621146088556
[769] exp: -0.24117766906255267
[770] exp: -0.24179322351624974
[771] exp: -0.2424087779699468
[772] exp: -0.24256286025472576
[773] exp: -0.24317841470842283
[774] exp: -0.2437939691621199
[775] exp: -0.24388015971144672
[776] exp: -0.2430025795504418
[777] exp: -0.24361813400413887
[778] exp: -0.24423368845783594
[779] exp: -0.2442418955889244
[780] exp: -0.24485745004262147
[781] exp: -0.24547300449631854
[782] exp: -0.2456807075066957
[783] exp: -0.24629626196039278
[784] exp: -0.24713400058278212
[785] exp: -0.24651844612908505
[786] exp: -0.24651844612908505
[787] exp: -0.24713400058278212
[788] exp: -0.2477495550364792
[789] exp: -0.24836510949017626
[790] exp: -0.24836510949017626
[791] exp: -0.24836510949017626
[792] exp: -0.24898066394387333
[793] exp: -0.2495962183975704
[794] exp: -0.2495962183975704
[795] exp: -0.25051117355932184
[796] exp: -0.25112672801301894
[797] exp: -0.25112672801301894
[798] exp: -0.25174228246671604
[799] exp: -0.25235783692041314
[800] exp: -0.25297339137411023
[801] exp: -0.25358894582780733
[802] exp: -0.25420450028150443
[803] exp: -0.25482005473520153
[804] exp: -0.2554356091888986
[805] exp: -0.2554356091888986
[806] exp: -0.2560511636425957
[807] exp: -0.2566667180962928
[808] exp: -0.2572822725499899
[809] exp: -0.257897827003687
[810] exp: -0.2585133814573841
[811] exp: -0.2591289359110812
[812] exp: -0.2597444903647783
[813] exp: -0.2603600448184754
[814] exp: -0.2609755992721725
[815] exp: -0.2615911537258696
[816] exp: -0.26194188750198566
[817] exp: -0.26194188750198566
[818] exp: -0.26255744195568276
[819] exp: -0.26317299640937986
[820] exp: -0.26255744195568276
[821] exp: -0.26255744195568276
[822] exp: -0.26255744195568276
[823] exp: -0.26317299640937986
[824] exp: -0.26378855086307695
[825] exp: -0.26440410531677405
[826] exp: -0.26440410531677405
[827] exp: -0.26501965977047115
[828] exp: -0.2658114564052007
[829] exp: -0.2658114564052007
[830] exp: -0.26654768954301
[831] exp: -0.26654768954301
[832] exp: -0.2657089792429236
[833] exp: -0.2663245336966207
[834] exp: -0.2663245336966207
[835] exp: -0.2669400881503178
[836] exp: -0.2669400881503178
[837] exp: -0.2675556426040149
[838] exp: -0.268171197057712
[839] exp: -0.26878675151140907
[840] exp: -0.268171197057712
[841] exp: -0.268171197057712
[842] exp: -0.268171197057712
[843] exp: -0.26878675151140907
[844] exp: -0.26940230596510617
[845] exp: -0.27001786041880327
[846] exp: -0.26940230596510617
[847] exp: -0.2696050634297452
[848] exp: -0.26894336376939737
[849] exp: -0.26955891822309447
[850] exp: -0.26955891822309447
[851] exp: -0.2700922968507422
[852] exp: -0.2700922968507422
[853] exp: -0.2700922968507422
[854] exp: -0.2707078513044393
[855] exp: -0.2713234057581364
[856] exp: -0.2713234057581364
[857] exp: -0.2713234057581364
[858] exp: -0.2719389602118335
[859] exp: -0.2723312986160437
[860] exp: -0.2729468530697408
[861] exp: -0.2735624075234379
[862] exp: -0.274177961977135
[863] exp: -0.274177961977135
[864] exp: -0.274177961977135
[865] exp: -0.2747935164308321
[866] exp: -0.2754090708845292
[867] exp: -0.2760246253382263
[868] exp: -0.2766401797919234
[869] exp: -0.2772557342456205
[870] exp: -0.2778712886993176
[871] exp: -0.2784868431530147
[872] exp: -0.2791023976067118
[873] exp: -0.2784868431530147
[874] exp: -0.2784868431530147
[875] exp: -0.2791023976067118
[876] exp: -0.2782980485067252
[877] exp: -0.27735874637169267
[878] exp: -0.27797430082538976
[879] exp: -0.27858985527908686
[880] exp: -0.27920540973278396
[881] exp: -0.27982096418648106
[882] exp: -0.27982096418648106
[883] exp: -0.27982096418648106
[884] exp: -0.28043651864017816
[885] exp: -0.28043651864017816
[886] exp: -0.28105207309387525
[887] exp: -0.28105207309387525
[888] exp: -0.28166762754757235
[889] exp: -0.28228318200126945
[890] exp: -0.28289873645496655
[891] exp: -0.2825211540269534
[892] exp: -0.2831367084806505
[893] exp: -0.2831367084806505
[894] exp: -0.2837522629343476
[895] exp: -0.2843678173880447
[896] exp: -0.2837522629343476
[897] exp: -0.2843347405672988
[898] exp: -0.2843347405672988
[899] exp: -0.2845791570436383
[900] exp: -0.2845791570436383
[901] exp: -0.2839636025899412
[902] exp: -0.2845791570436383
[903] exp: -0.2839636025899412
[904] exp: -0.2833480481362441
[905] exp: -0.2839636025899412
[906] exp: -0.2845791570436383
[907] exp: -0.2851947114973354
[908] exp: -0.28543574532739174
[909] exp: -0.28605129978108884
[910] exp: -0.28605129978108884
[911] exp: -0.28529738883815065
[912] exp: -0.28529738883815065
[913] exp: -0.2859254146897928
[914] exp: -0.2868482797677258
[915] exp: -0.2874638342214229
[916] exp: -0.28807938867512
[917] exp: -0.28807938867512
[918] exp: -0.2886949431288171
[919] exp: -0.28960982734083196
[920] exp: -0.29022538179452906
[921] exp: -0.29084093624822616
[922] exp: -0.29145649070192325
[923] exp: -0.29207204515562035
[924] exp: -0.29268759960931745
[925] exp: -0.29268759960931745
[926] exp: -0.29330315406301455
[927] exp: -0.29391870851671165
[928] exp: -0.29391870851671165
[929] exp: -0.29453426297040874
[930] exp: -0.29545259668810003
[931] exp: -0.29545259668810003
[932] exp: -0.29483704223440294
[933] exp: -0.29545259668810003
[934] exp: -0.29606815114179713
[935] exp: -0.29606815114179713
[936] exp: -0.29668370559549423
[937] exp: -0.2972992600491913
[938] exp: -0.2979148145028884
[939] exp: -0.2979148145028884
[940] exp: -0.2979148145028884
[941] exp: -0.2979148145028884
[942] exp: -0.2985303689565855
[943] exp: -0.2991459234102826
[944] exp: -0.2991459234102826
[945] exp: -0.2991459234102826
[946] exp: -0.2997614778639797
[947] exp: -0.2997614778639797
[948] exp: -0.2997614778639797
[949] exp: -0.3003770323176768
[950] exp: -0.3013107890652462
[951] exp: -0.3013107890652462
[952] exp: -0.3004164880131131
[953] exp: -0.299800933559416
[954] exp: -0.30024286071658635
[955] exp: -0.29962730626288925
[956] exp: -0.30024286071658635
[957] exp: -0.3002399965717314
[958] exp: -0.3008555510254285
[959] exp: -0.3014711054791256
[960] exp: -0.3008555510254285
[961] exp: -0.3014711054791256
[962] exp: -0.3014711054791256
[963] exp: -0.3014711054791256
[964] exp: -0.3020866599328227
[965] exp: -0.3020866599328227
[966] exp: -0.3027022143865198
[967] exp: -0.3033177688402169
[968] exp: -0.303933323293914
[969] exp: -0.3045488777476111
[970] exp: -0.3051644322013082
[971] exp: -0.3051644322013082
[972] exp: -0.3051644322013082
[973] exp: -0.30424607952190996
[974] exp: -0.3036183112721912
[975] exp: -0.3042338657258883
[976] exp: -0.3048494201795854
[977] exp: -0.3054649746332825
[978] exp: -0.30453069264814825
[979] exp: -0.30514624710184535
[980] exp: -0.30433271597198613
[981] exp: -0.30512125684171765
[982] exp: -0.30512125684171765
[983] exp: -0.30450570238802055
[984] exp: -0.30476178907673923
[985] exp: -0.30537734353043633
[986] exp: -0.3059928979841334
[987] exp: -0.3059928979841334
[988] exp: -0.3066084524378305
[989] exp: -0.3072240068915276
[990] exp: -0.3072240068915276
[991] exp: -0.3072240068915276
[992] exp: -0.3076771002911508
[993] exp: -0.3076771002911508
[994] exp: -0.3082926547448479
[995] exp: -0.3082926547448479
[996] exp: -0.308908209198545
[997] exp: -0.308908209198545
[998] exp: -0.3095237636522421
[999] exp: -0.3101393181059392
CPTP mapping

CPTP is created by giving a list of Claus operators that satisfy the completeness.

[27]:
from qulacs.gate import merge,CPTP, P0,P1

gate00 = merge(P0(0),P0(1))
gate01 = merge(P0(0),P1(1))
gate10 = merge(P1(0),P0(1))
gate11 = merge(P1(0),P1(1))

gate_list = [gate00, gate01, gate10, gate11]
gate = CPTP(gate_list)

from qulacs import QuantumState
from qulacs.gate import H,merge
state = QuantumState(2)
for _ in range(10):
    state.set_zero_state()
    merge(H(0),H(1)).update_quantum_state(state)
    gate.update_quantum_state(state)
    print(state.get_vector())
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 0.+0.j 1.+0.j]
[1.+0.j 0.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]
[0.+0.j 1.+0.j 0.+0.j 0.+0.j]
[0.+0.j 0.+0.j 0.+0.j 1.+0.j]
[0.+0.j 0.+0.j 1.+0.j 0.+0.j]

The AmplitudeDampingNoise gate is defined as CPTP-map.

[28]:
from qulacs.gate import AmplitudeDampingNoise
target = 0
damping_rate = 0.1
AmplitudeDampingNoise(target, damping_rate)
#K_0: [[1,0],[0,sqrt(1-p)]], K_1: [[0,sqrt(p)], [0,0]]
[28]:
 *** gate info ***
 * gate name : Generic gate
 * target    :
 * control   :
 * Pauli     : no
 * Clifford  : no
 * Gaussian  : no
 * Parametric: no
 * Diagonal  : yes
Instrument

Instrument is an operation to get the index of the Claus operator that acts randomly in addition to the general CPTP-map operation. For example, measurement on the Z basis is equivalent to applying a CPTP-map consisting of P0 and P1 and knowing which one has acted. In cppsim, this is achieved in the Instrument function, by specifying the information of the CPTP-map and the address of the classic register in which the index of the operated Claus operator is written.

[29]:
from qulacs import QuantumState
from qulacs.gate import merge,Instrument, P0,P1

gate00 = merge(P0(0),P0(1))
gate01 = merge(P1(0),P0(1))
gate10 = merge(P0(0),P1(1))
gate11 = merge(P1(0),P1(1))

gate_list = [gate00, gate01, gate10, gate11]
classical_pos = 0
gate = Instrument(gate_list, classical_pos)

from qulacs import QuantumState
from qulacs.gate import H,merge
state = QuantumState(2)
for index in range(10):
    state.set_zero_state()
    merge(H(0),H(1)).update_quantum_state(state)
    gate.update_quantum_state(state)
    result = state.get_classical_value(classical_pos)
    print(index, format(result,"b").zfill(2), state.get_vector())
0 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
1 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
2 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
3 10 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]
4 00 [1.+0.j 0.+0.j 0.+0.j 0.+0.j]
5 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]
6 11 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]
7 11 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]
8 00 [1.+0.j 0.+0.j 0.+0.j 0.+0.j]
9 10 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]

Note that Measurement gate is defined as Instrument.

[30]:
from qulacs.gate import Measurement
target = 0
classical_pos = 0
gate = Measurement(target, classical_pos)
Adaptive operation

This is a gate that uses a function that returns a Boolean value with variable-length list of classical register values as an argument, and determines whether to perform an operation according to the conditions obtained from the classical register. Conditions can be written as python functions. A python function must be a function that takes a list of type int as an argument and returns a bool type value.

[31]:
from qulacs.gate import Adaptive, X

def func(list):
    print("func is called! content is ",list)
    return list[0]==1


gate = Adaptive(X(0), func)

state = QuantumState(1)
state.set_zero_state()

# func returns False, so X does not operate
state.set_classical_value(0,0)
gate.update_quantum_state(state)
print(state.get_vector())

# func returns True, so X operates
state.set_classical_value(0,1)
gate.update_quantum_state(state)
print(state.get_vector())
func is called! content is  [0]
[1.+0.j 0.+0.j]
func is called! content is  [1]
[0.+0.j 1.+0.j]

Operator

Pauli operator

Observables are represented as linear combinations of Pauli operators with real coefficients. PauliOperator class is a class that expresses each term with the coefficient added to the \(n\)-qubit Pauli operator. Unlike gates, operator cannot update quantum states.

Create Pauli operator and obtain state
[32]:
from qulacs import PauliOperator
coef = 0.1
s = "X 0 Y 1 Z 3"
pauli = PauliOperator(s, coef)

# Added pauli symbol later
pauli.add_single_Pauli(3, 2)

# Get the subscript of each pauli symbol
index_list = pauli.get_index_list()

# Get pauli symbols (I,X,Y,Z -> 0,1,2,3)
pauli_id_list = pauli.get_pauli_id_list()

# Get pauli coefficient
coef = pauli.get_coef()

# Create a copy of pauli operator
another_pauli = pauli.copy()

s = ["I","X","Y","Z"]
pauli_str = [s[i] for i in pauli_id_list]
terms_str = [item[0]+str(item[1]) for item in zip(pauli_str,index_list)]
full_str = str(coef) + " " + " ".join(terms_str)
print(full_str)
(0.1+0j) X0 Y1 Z3 Y3
Expected value of Pauli operator

You can evaluate the expected value and transition moment of the Pauli operator for one state.

[33]:
from qulacs import PauliOperator, QuantumState

n = 5
coef = 2.0
Pauli_string = "X 0 X 1 Y 2 Z 4"
pauli = PauliOperator(Pauli_string,coef)

# Calculate expectation value <a|H|a>
state = QuantumState(n)
state.set_Haar_random_state()
value = pauli.get_expectation_value(state)
print("expect", value)

# Calculate transition moment <a|H|b>
# The first arguments comes to the bra side
bra = QuantumState(n)
bra.set_Haar_random_state()
value = pauli.get_transition_amplitude(bra, state)
print("transition", value)
expect (0.6132028798856664+0j)
transition (0.5279713648817308-0.6040063466314933j)
General linear operators

The linear operator GeneralQuantumOperator is represented by a linear combination of the Pauli operators with a complex coefficient. PauliOperator with coefficient can be added as a term with add_operator.

[34]:
from qulacs import GeneralQuantumOperator, PauliOperator, QuantumState

n = 5
operator = GeneralQuantumOperator(n)

# Pauli operator can be added
coef = 2.0+0.5j
Pauli_string = "X 0 X 1 Y 2 Z 4"
pauli = PauliOperator(Pauli_string,coef)
operator.add_operator(pauli)
# Pauli operator can also be added directly from coefficients and strings
operator.add_operator(0.5j, "Y 1 Z 4")

# Get number of terms
term_count = operator.get_term_count()

# Get number of quantum bit
qubit_count = operator.get_qubit_count()

# Get specific terms as PauliOperator
index = 1
pauli = operator.get_term(index)


# Expected value calculation <a|H|a>
## Generally not self-adjoint, can return complex value
state = QuantumState(n)
state.set_Haar_random_state()
value = operator.get_expectation_value(state)
print("expect", value)

# Transition moment calculation <a|H|b>
# The first arguments comes to the bra side
bra = QuantumState(n)
bra.set_Haar_random_state()
value = operator.get_transition_amplitude(bra, state)
print("transition", value)
expect (-0.12123883067235244+0.004874745096201068j)
transition (-0.19076380005803-0.03521147847936834j)
Generation of observables using OpenFermion

OpenFermion is a tool that gives Hamiltonian to be solved by chemical calculation in the form of Pauli operator. The output of this tool can be read in the form of a file or a string and can be used in the form of an operator.

[35]:
from qulacs.quantum_operator import create_quantum_operator_from_openfermion_file
from qulacs.quantum_operator import create_quantum_operator_from_openfermion_text

open_fermion_text = """
(-0.8126100000000005+0j) [] +
(0.04532175+0j) [X0 Z1 X2] +
(0.04532175+0j) [X0 Z1 X2 Z3] +
(0.04532175+0j) [Y0 Z1 Y2] +
(0.04532175+0j) [Y0 Z1 Y2 Z3] +
(0.17120100000000002+0j) [Z0] +
(0.17120100000000002+0j) [Z0 Z1] +
(0.165868+0j) [Z0 Z1 Z2] +
(0.165868+0j) [Z0 Z1 Z2 Z3] +
(0.12054625+0j) [Z0 Z2] +
(0.12054625+0j) [Z0 Z2 Z3] +
(0.16862325+0j) [Z1] +
(-0.22279649999999998+0j) [Z1 Z2 Z3] +
(0.17434925+0j) [Z1 Z3] +
(-0.22279649999999998+0j) [Z2]
"""

operator = create_quantum_operator_from_openfermion_text(open_fermion_text)
print(operator.get_term_count())
print(operator.get_qubit_count())
# In the case of create_quantum_operator_from_openfermion_file, specify the path of the file where the above is written in the argument.
15
4
Hermite operator / observable

The Hermite operator is represented by a real linear combination of the Pauli operators. Equivalent to the GeneralQuatnumOperator class, except that eigenvalues and expected values are guaranteed to be real.

The function to read and process from an external file is possible by replacing the quantum_operator with the observable, and using functions such as create_observable_from_openfermion_file create_observable_from_openfermion_text create_split_observable.

Separates operators into diagonal and off-diagonal terms

When reading an operator from a file, you can separate it into diagonal and off-diagonal components with the create_split_observable function.

[ ]:
from qulacs.observable import create_split_observable, create_observable_from_openfermion_file

# H2.txt must be placed in openfermon format beforehand.
operator = create_observable_from_openfermion_file("./H2.txt")
diag, nondiag = create_split_observable("./H2.txt")
print(operator.get_term_count(), diag.get_term_count(), nondiag.get_term_count())
print(operator.get_qubit_count(), diag.get_qubit_count(), nondiag.get_qubit_count())
Compute ground state

You can compute a ground state of the operator by power method, Arnoldi method or Lanczos method. After computation, the corresponding ground state is assigned to state in the argument.

Power method
[ ]:
from qulacs import Observable, QuantumState
from qulacs.observable import create_observable_from_openfermion_file

n = 4
operator = create_observable_from_openfermion_file("./H2.txt")
state = QuantumState(n)
state.set_Haar_random_state()
value = operator.solve_ground_state_eigenvalue_by_power_method(state, 50)
print(value)
Arnoldi method
[ ]:
from qulacs import Observable, QuantumState
from qulacs.observable import create_observable_from_openfermion_file

n = 4
operator = create_observable_from_openfermion_file("./H2.txt")
state = QuantumState(n)
state.set_Haar_random_state()
value = operator.solve_ground_state_eigenvalue_by_arnoldi_method(state, 50)
print(value)
Lanczos method
[ ]:
from qulacs import Observable, QuantumState
from qulacs.observable import create_observable_from_openfermion_file

n = 4
operator = create_observable_from_openfermion_file("./H2.txt")
state = QuantumState(n)
state.set_Haar_random_state()
value = operator.solve_ground_state_eigenvalue_by_lanczos_method(state, 50)
print(value)
Apply to a quantum state

An operator can be applied to a quantum state.

[ ]:
from qulacs import Observable, QuantumState
from qulacs.observable import create_observable_from_openfermion_file

n = 4
operator = create_observable_from_openfermion_file("./H2.txt")
state = QuantumState(n)
state.set_Haar_random_state()
result = QuantumState(n)
work_state = QuantumState(n)
operator.apply_to_state(work_state, state, result)
print(result)

Quantum Circuits

Structure of a quantum circuit

A quantum circuit is represented as a set of quantum gates. For example, a quantum circuit can be configured as follows.

[37]:
from qulacs import QuantumState, QuantumCircuit
from qulacs.gate import Z
n = 3
state = QuantumState(n)
state.set_zero_state()

circuit = QuantumCircuit(n)

# Add hadamard gate to quantum circuit
for i in range(n):
    circuit.add_H_gate(i)

# Create gate, which can also be added
for i in range(n):
    circuit.add_gate(Z(i))

# Operate quantum circuit to state
circuit.update_quantum_state(state)

print(state.get_vector())
[ 0.35355339+0.j -0.35355339-0.j -0.35355339-0.j  0.35355339+0.j
 -0.35355339-0.j  0.35355339+0.j  0.35355339+0.j -0.35355339-0.j]
Calculation and optimization of depth of quantum circuits

By combining quantum gates into a single quantum gate, the number of quantum gates and the time required for numerical calculations can be reduced. (Of course, if the number of target qubits increases, or if a quantum gate with a dedicated function is synthesized into a quantum gate without a dedicated function, the total calculation time may not decrease. It depends.)

The code below uses the optimize function to repeat the greedy synthesis of the quantum gate of the quantum circuit until the target qubit becomes three.

[38]:
from qulacs import QuantumCircuit
from qulacs.circuit import QuantumCircuitOptimizer
n = 5
depth = 10
circuit = QuantumCircuit(n)
for d in range(depth):
    for i in range(n):
        circuit.add_H_gate(i)

# Calculate the depth (depth=10)
print(circuit.calculate_depth())

# Optimization
opt = QuantumCircuitOptimizer()
# The maximum quantum gate size allowed to be created
max_block_size = 1
opt.optimize(circuit, max_block_size)

# Calculate the depth (depth=1へ)
print(circuit.calculate_depth())
10
1
Debugging quantum circuits

When print a quantum circuit, statistical information about the gates included in the quantum circuit will be displayed.

[39]:
from qulacs import QuantumCircuit
from qulacs.circuit import QuantumCircuitOptimizer
n = 5
depth = 10
circuit = QuantumCircuit(n)
for d in range(depth):
    for i in range(n):
        circuit.add_H_gate(i)

print(circuit)
*** Quantum Circuit Info ***
# of qubit: 5
# of step : 10
# of gate : 50
# of 1 qubit gate: 50
Clifford  : yes
Gaussian  : no


Parametric Quantum Circuits

Defining a quantum circuit as a ParametricQuantumCircuit class enables some functions that are useful for optimizing quantum circuits using variational methods, in addition to the usual functions of the QuantumCircuit class.

Application examples of parametric quantum circuits

Quantum gates with one rotation angle (RX, RY, RZ, multi_qubit_pauli_rotation) can be added to quantum circuits as parametric quantum gates. For a quantum gate added as a parametric gate, the number of parametric gates can be extracted after the quantum circuit is configured, and the rotation angle can be changed later.

[40]:
from qulacs import ParametricQuantumCircuit
from qulacs import QuantumState
import numpy as np

n = 5
depth = 10

# construct parametric quantum circuit with random rotation
circuit = ParametricQuantumCircuit(n)
for d in range(depth):
    for i in range(n):
        angle = np.random.rand()
        circuit.add_parametric_RX_gate(i,angle)
        angle = np.random.rand()
        circuit.add_parametric_RY_gate(i,angle)
        angle = np.random.rand()
        circuit.add_parametric_RZ_gate(i,angle)
    for i in range(d%2, n-1, 2):
        circuit.add_CNOT_gate(i,i+1)

# add multi-qubit Pauli rotation gate as parametric gate (X_0 Y_3 Y_1 X_4)
target = [0,3,1,4]
pauli_ids = [1,2,2,1]
angle = np.random.rand()
circuit.add_parametric_multi_Pauli_rotation_gate(target, pauli_ids, angle)

# get variable parameter count, and get current parameter
parameter_count = circuit.get_parameter_count()
param = [circuit.get_parameter(ind) for ind in range(parameter_count)]

# set 3rd parameter to 0
circuit.set_parameter(3, 0.)

# update quantum state
state = QuantumState(n)
circuit.update_quantum_state(state)

# output state and circuit info
print(state)
print(circuit)
 *** Quantum State ***
 * Qubit Count : 5
 * Dimension   : 32
 * State vector :
   (0.0292587,0.0842756)
   (-0.0199201,0.242442)
    (0.181468,-0.104986)
  (0.0995482,-0.0233467)
     (0.16811,0.0345288)
   (0.0562338,-0.225101)
    (-0.131558,0.100174)
    (0.144257,-0.120167)
  (-0.173724,-0.0457571)
  (-0.142581,-0.0917222)
     (0.210296,0.176269)
   (0.0014233,0.0511538)
   (-0.00440611,0.26444)
   (0.0175043,0.0854573)
    (-0.197366,0.133705)
     (0.191306,0.316103)
   (-0.132828,-0.128943)
   (-0.00599114,0.03745)
  (-0.203638,-0.0249769)
   (-0.157577,0.0372862)
   (-0.132844,-0.105019)
  (-0.136556,-0.0918098)
   (-0.0584003,0.043396)
    (-0.02902,0.0680596)
   (0.0952735,-0.052631)
   (0.0738972,-0.127688)
   (0.165229,-0.0591462)
(0.0608202,-0.000749349)
  (-0.0873545,0.0887971)
    (-0.12346,0.0469901)
 (0.0344535,-0.00645451)
   (-0.216478,0.0550732)

*** Quantum Circuit Info ***
# of qubit: 5
# of step : 41
# of gate : 171
# of 1 qubit gate: 150
# of 2 qubit gate: 20
# of 3 qubit gate: 0
# of 4 qubit gate: 1
Clifford  : no
Gaussian  : no

*** Parameter Info ***
# of parameter: 151

Compute a gradient of parametric quantum circuit

You can compute a gradient of parametric circuit by GradCalculator or ParametricQuantumCircuit.backprop().

  • In GradCalculator, compute a gradient by calculating expected value with CausalConeSimulator.

  • In ParametricQuantumCircuit.backprop(), compute a gradient by back propagation.

[5]:
from qulacs import ParametricQuantumCircuit, GradCalculator, Observable

n = 2
observable = Observable(n)
observable.add_operator(1.0, "X 0")
circuit = ParametricQuantumCircuit(n)

theta = [2.2, 1.4, 0.8]
circuit.add_parametric_RX_gate(0, theta[0])
circuit.add_parametric_RY_gate(0, theta[1])
circuit.add_parametric_RZ_gate(0, theta[2])

# GradCalculatorの場合
gcalc = GradCalculator()
print(gcalc.calculate_grad(circuit, observable))
# 第三引数に回転角を指定することも可能
print(gcalc.calculate_grad(circuit, observable, theta))
# Backpropを使って求めた場合
print(circuit.backprop(observable))
[(0.1329240611221506+0j), (0.06968868323709176+0j), (0.14726262077628172+0j)]
[(0.1329240611221506+0j), (0.06968868323709176+0j), (0.14726262077628172+0j)]
[0.1329240611221506, 0.06968868323709171, 0.14726262077628177]

Simulator

QuantumCircuitSimulator

You can manage a circuit and quantum states together. It has a buffer for quantum state to swap the state to use.

[6]:
from qulacs import QuantumState, QuantumCircuit, QuantumCircuitSimulator, Observable
n = 3
state = QuantumState(n)

# 回路を作成
circuit = QuantumCircuit(n)
for i in range(n):
   circuit.add_H_gate(i)

# シミュレータクラスを作成
sim = QuantumCircuitSimulator(circuit, state)

# 基底を二進数と見た時の整数値を入れて、その状態に初期化
sim.initialize_state(0)

# ゲート数
print("gate_count: ", sim.get_gate_count())

# 実行
sim.simulate()

# 量子状態を表示
print(state)

# 期待値
observable = Observable(1)
observable.add_operator(1.0, "Z 0")
print("expectation_value: ", sim.get_expectation_value(observable))

# 量子状態を入れ替え
print("swap")
sim.swap_state_and_buffer()
# ランダムな純粋状態へ初期化
sim.initialize_random_state(seed=0)
sim.simulate()
print(state)

# 量子状態をコピー(バッファ->現状態)
sim.copy_state_from_buffer()
sim.simulate()
print(state)

# 量子状態をコピー(現状態->バッファ)
sim.copy_state_to_buffer()
sim.simulate()
print(state)
gate_count:  3
 *** Quantum State ***
 * Qubit Count : 3
 * Dimension   : 8
 * State vector :
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)

expectation_value:  0j
swap
 *** Quantum State ***
 * Qubit Count : 3
 * Dimension   : 8
 * State vector :
  (-0.298916,0.160953)
  (0.015405,-0.237144)
  (-0.215765,0.171064)
(-0.257959,-0.0506326)
 (-0.121612,0.0424348)
(-0.0329899,-0.400262)
  (0.327376,-0.414262)
   (0.345253,0.327824)

 *** Quantum State ***
 * Qubit Count : 3
 * Dimension   : 8
 * State vector :
(1,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)
(0,0)

 *** Quantum State ***
 * Qubit Count : 3
 * Dimension   : 8
 * State vector :
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)
(0.353553,0)

NoiseSimulator

The NoiseSimulator allows you to run your circuit in a simulated noise environment.

To set up noise, you should add a gate to the circuit using add_noise_gate(). The first argument specifies the gate, the second the type of noise to add ("Depolarizing" / "BitFlip" / "Dephasing" / "IndependentXZ" / "AmplitudeDamping"), and the third the probability of noise generation. In the case of a two-qubit gate, you can use "Depolarizing" only.

[7]:
import random
from qulacs import QuantumState, QuantumCircuit, NoiseSimulator
from qulacs.gate import sqrtX, sqrtY, T, CNOT, CZ

n = 3
depth = 10
one_qubit_noise = ["Depolarizing", "BitFlip", "Dephasing", "IndependentXZ", "AmplitudeDamping"]
circuit = QuantumCircuit(n)

for d in range(depth):
   for i in range(n):
      r = random.randint(0, 4)
      noise_type = random.randint(0, 4)
      if r == 0:
            circuit.add_noise_gate(sqrtX(i), one_qubit_noise[noise_type], 0.01)
      elif r == 1:
            circuit.add_noise_gate(sqrtY(i), one_qubit_noise[noise_type], 0.01)
      elif r == 2:
            circuit.add_noise_gate(T(i), one_qubit_noise[noise_type], 0.01)
      elif r == 3:
            if i + 1 < n:
               circuit.add_noise_gate(CNOT(i, i+1), "Depolarizing", 0.01)
      elif r == 4:
            if i + 1 < n:
               circuit.add_noise_gate(CZ(i, i+1), "Depolarizing", 0.01)

state = QuantumState(n)
state.set_Haar_random_state()
sim = NoiseSimulator(circuit, state)
sim.execute(100)
print(state)
 *** Quantum State ***
 * Qubit Count : 3
 * Dimension   : 8
 * State vector :
  (0.424423,-0.125395)
 (0.0193726,-0.298116)
  (-0.357495,0.227471)
   (0.0119428,0.13876)
 (-0.351555,0.0521885)
    (0.230969,0.21148)
 (0.274671,-0.0305064)
(-0.462659,-0.0337342)

CausalConeSimulator

CausalConeSimulator allows you to extract the gates associated with a given observable by traversing the circuit in reverse. Only the extracted gates can be applied to obtain the expected value of the physical quantity.

This allows you to find the expected value of a circuit of large size qubits, since the shallower the depth of the circuit, the fewer the gates associated with it.

[8]:
from qulacs import QuantumState, ParametricQuantumCircuit, CausalConeSimulator, Observable
n = 100
observable = Observable(1)
observable.add_operator(1.0, "Z 0")
circuit = ParametricQuantumCircuit(n)
for i in range(n):
   circuit.add_parametric_RX_gate(i, 1.0)
   circuit.add_parametric_RY_gate(i, 1.0)

ccs = CausalConeSimulator(circuit, observable)
print(ccs.get_expectation_value())
(0.2919265817264289+0j)

Implementing Quantum Algorithms

This chapter consists a collection of notebooks showing how to use qulacs to study quantum computing algorithms

Quantum Circuit Learning

Quantum Circuit Learning (QCL) is an algorithm for applying quantum computers to machine learning [1]. Just like the VQE (Variational Quantum Eigensolver) we have learned in the previous section, it is a quantum-classical hybrid algorithm, designed to operate on NISQ (Noisy Intermediate-Scale Quantum Computer), a medium-scale quantum computer without error correction function.

Experiments using actual NISQ devices have already been performed, and in March 2019, a paper on actual implementation of QCL by an IBM experiment team [2] was published in Nature and became a hot topic.

In the following, the outline of the algorithm and the specific learning procedure are introduced, then an implementation example using the quantum simulator Qulacs is presented.

This notebook is tranlated from https://dojo.qulacs.org/ja/latest/notebooks/5.1_variational_quantum_eigensolver.html

Overview of QCL

In recent years, deep learning has been spotlighted in the field of machine learning. In deep learning, by approximating a complex function using a deep neural network, the relationship between input and output can be learned and predictions can be performed on new data. QCL is a machine learning method that replaces this neural network with a quantum circuit, and hence a quantum computer.

By using the quantum circuit, the learning process can be performed exponentially by using a large number of basis functions by utilizing the principle of superposition of quantum mechanics, so that the expression capacity of the model is improved.

Furthermore, it is considered that overfitting can be automatically prevented depending on the condition (unitary property) to be satisfied by the quantum circuit. As a result, higher performance can be expected beyond machine learning in classical computers. (See Reference [1] for details)

In a neural network, the function is approximated by adjusting the weight parameter W of each layer, and the concept is exactly the same in QCL.

That is, although the quantum circuit used in the QCL includes multiple “rotating gates”, the function is approximated by adjusting the rotating angle \(\theta\) of the rotating gate. The specific procedure is shown below.

Learning procedure
  1. Prepare training data {(\(x_i,y_i\))}. (\(x_i\) is input data (teacher data), \(y_i\) is the correct output data expected to be predicted from \(x_i\))

  2. Prepare a circuit called \(U_\text{in}(x)\) that is determined by some rule from the input \(x\), and create an input state \(\{\left|\psi_{\text{in}}(x_i)\right>\}_i=\{U_{\text{in}}(x_i)\left|0\right>\}_i\) with the information of \(x_i\) embedded.

  3. Multiply gate \(U(\theta)\) which depends on parameter \(\theta\) with the input state to obtain the output state \(\{\left|\psi_{\text{out}}(x_i,\theta)\right>=U(\theta)\left|\psi_{\text{in}}(x_i)\right>\}_i\).

  4. The measurement is done by measuring some observable under the output state. (eg. the \(Z\) expection of the first qubit: \(\left<Z_1\right>=\left<\psi_{\text{out}}\left|Z_1\right|\psi_{\text{out}}\right>\))

  5. Set F as an appropriate function (sigmoid, softmax or constant function, etc.), and the output \(y(x_i,\theta)\) of the model is F(measurement_i).

  6. Calculate the cost function \(L(\theta)\) representing the divergence between the correct data \(\{y_i\}\) and the output \(\{y(x_i,\theta)\}_i\) of the model.

  7. Obtain the \(\theta=\theta^*\) which minimizes the cost function.

  8. Then \(y(x,\theta^*)\) is the desired prediction model.

QCL.png

(In the QCL, input data \(x\) is first converted to a quantum state using \(U_{\text{in}}(x)\), and an output \(y\) is obtained there from using a variational quantum circuit \(U(\theta)\) and measurement (In the figure, the output is \(\left<B(x,\theta)\right>\).) Source: Revised Figure 1 in reference [1].)

Implementation using quantum simulator Qulacs

In the following, a fitting of sin function \(y=sin(\pi x)\) is performed as a demonstration of approximating function.

[2]:
import numpy as np
import matplotlib.pyplot as plt
from functools import reduce
[3]:
########  Parameter  #############
nqubit = 3 ## number of qubit
c_depth = 3 ## depth of circuit
time_step = 0.77  ## elapsed time of time evolution with random Hamiltonian

## randomly take num_x_train points from [x_min, x_max] as teacher data.
x_min = - 1.; x_max = 1.;
num_x_train = 50

## one variable function to learn
func_to_learn = lambda x: np.sin(x*np.pi)

## seed of random number
random_seed = 0
## initialization of random number generator
np.random.seed(random_seed)
Prepare training data
[4]:
#### Prepare teacher data
x_train = x_min + (x_max - x_min) * np.random.rand(num_x_train)
y_train = func_to_learn(x_train)

# Add noise to pure sine function assuming real data used
mag_noise = 0.05
y_train = y_train + mag_noise * np.random.randn(num_x_train)

plt.plot(x_train, y_train, "o"); plt.show()
_images/apply_5.2_qcl_7_0.png
Construct the input state

Firstly, create a gate \(U_{\text{in}}(x_i)\) for embedding the input value \(x_i\) in the initial state \(\left|00...0\right>\). According to reference [1], define \(U_{\text{in}}(x_i)=\prod_jR^Z_j(\text{cos}^{-1}x^2)R^Y_j(\text{sin}^{-1}x)\) using rotation gates \(R^Y_j(\theta)=e^{i\theta Y_j/2}, R^Z_j(\theta)=e^{i\theta Z_j/2}\). The input \(x_i\) is converted into quantum state \(\left|\psi_\text{in}(x_i)\right>=U_{\text{in}}(x_i)\left|00...0\right>\).

[5]:
## When using Google Colaboratory・please run in a local environment where Qulacs is not installed.
!pip install qulacs
Requirement already satisfied: qulacs in /anaconda3/envs/VibSpec/lib/python3.7/site-packages (0.1.9)
[6]:
# Create intial state
from qulacs import QuantumState, QuantumCircuit

state = QuantumState(nqubit) # Initial state |000>
state.set_zero_state()
print(state.get_vector())
[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]
[7]:
# Function that creats a gate encoding x
def U_in(x):
    U = QuantumCircuit(nqubit)

    angle_y = np.arcsin(x)
    angle_z = np.arccos(x**2)

    for i in range(nqubit):
        U.add_RY_gate(i, angle_y)
        U.add_RZ_gate(i, angle_z)

    return U
[8]:
# Test initial state
x = 0.1 # appropriate value
U_in(x).update_quantum_state(state) # calculation of U_in|000>
print(state.get_vector())
[-6.93804351e-01+7.14937415e-01j -3.54871219e-02-3.51340074e-02j
 -3.54871219e-02-3.51340074e-02j  1.77881430e-03-1.76111422e-03j
 -3.54871219e-02-3.51340074e-02j  1.77881430e-03-1.76111422e-03j
  1.77881430e-03-1.76111422e-03j  8.73809020e-05+9.00424970e-05j]
Construct variational quantum circuit \(U(\theta)\)

Next, a variational quantum circuit \(U(\theta)\) to be optimized is created. The procedure is the following three steps: 1. Create a transverse magnetic field Ising Hamiltonian. 2. Create rotation gates. 3. Combine step1 and step2’s gates alternatively to make a large variational quantum circuit \(U(\theta)\).

1.Create a transverse magnetic field Ising Hamiltonian

The expressiveness of the model is enhanced by increasing the complexity (entanglement) of the quantum circuit after performing time evolution based on the transverse magnetic field Ising model learned in section 4-2. (This part can be skipped unless you want to know the details.)

The Hamiltonian of transverse magnetic file Ising model is shown below, time evolution operator is defined as \(U_{\text{rand}}=e^{-iHt}\):

\begin{equation} H=\sum_{j=1}^N a_jX_j+\sum_{j=1}^N\sum_{k=1}^{j-1}J_{jk}Z_jZ_k \end{equation}

Coefficient \(a\) and \(J\) is a uniform distribution of \([-1,1]\).

[9]:
## Basic gate
from qulacs.gate import X, Z
I_mat = np.eye(2, dtype=complex)
X_mat = X(0).get_matrix()
Z_mat = Z(0).get_matrix()
[10]:
## Function that creates fullsize gate.
def make_fullgate(list_SiteAndOperator, nqubit):
    '''
    Take list_SiteAndOperator = [ [i_0, O_0], [i_1, O_1], ...],
    Insert Identity into unrelated qubit
    make (2**nqubit, 2**nqubit) matrix:
    I(0) * ... * O_0(i_0) * ... * O_1(i_1) ...
    '''
    list_Site = [SiteAndOperator[0] for SiteAndOperator in list_SiteAndOperator]
    list_SingleGates = [] ## Arrange 1-qubit gates and reduce with np.kron
    cnt = 0
    for i in range(nqubit):
        if (i in list_Site):
            list_SingleGates.append( list_SiteAndOperator[cnt][1] )
            cnt += 1
        else: ## an empty site is identity
            list_SingleGates.append(I_mat)

    return reduce(np.kron, list_SingleGates)
[11]:
#### Create time evolution operator by making random magnetic field and random coupling Ising Hamiltonian
ham = np.zeros((2**nqubit,2**nqubit), dtype = complex)
for i in range(nqubit): ## i runs 0 to nqubit-1
    Jx = -1. + 2.*np.random.rand() ## random number in -1~1
    ham += Jx * make_fullgate( [ [i, X_mat] ], nqubit)
    for j in range(i+1, nqubit):
        J_ij = -1. + 2.*np.random.rand()
        ham += J_ij * make_fullgate ([ [i, Z_mat], [j, Z_mat]], nqubit)

## Create a time evolution operator by diagonalization. H*P = P*D <-> H = P*D*P^dagger
diag, eigen_vecs = np.linalg.eigh(ham)
time_evol_op = np.dot(np.dot(eigen_vecs, np.diag(np.exp(-1j*time_step*diag))), eigen_vecs.T.conj()) # e^-iHT
[12]:
time_evol_op.shape
[12]:
(8, 8)
[13]:
# Convert to qulacs gate
from qulacs.gate import DenseMatrix
time_evol_gate = DenseMatrix([i for i in range(nqubit)], time_evol_op)
2.Create rotation gates, 3.Create \(U(\theta)\)

Combine the time evolution operator \(U_{\text{rand}}\) accroding to random transverse magnetic field Ising model and the operator of rotation gates operating on \(j(=1,2,\dots n)\)th qubit

\begin{equation} U_\text{rot}(\theta_j^{(i)})=R_j^X(\theta_{j1}^{(i)})R_j^Z(\theta_{j2}^{(i)})R_j^X(\theta_{j3}^{(i)}) \end{equation}

to create variational quantum circuit \(U(\theta)\):

\begin{equation} U\Big(\{\theta_j^{(i)}\}_{i,j}\Big)= \prod_{i=1}^d\bigg(\bigg(\prod_{j=1}^nU_\text{rot}(\theta_j^{(i)})\bigg)\cdot U_\text{rand} \bigg) \end{equation}

Here \(i\) is a suffix representing the layer of the quantum circuit, and \(U_\text{rand}\) and the above rotation are repeated in \(d\) layers in total. There are \(3\times n \times d\) parameters. The intial value of each \(\theta\) is a uniform distribution of \([0,2\pi]\).

[14]:
from qulacs import ParametricQuantumCircuit
[15]:
# Assemble output gate U_out & set initial parameter values
U_out = ParametricQuantumCircuit(nqubit)
for d in range(c_depth):
    U_out.add_gate(time_evol_gate)
    for i in range(nqubit):
        angle = 2.0 * np.pi * np.random.rand()
        U_out.add_parametric_RX_gate(i,angle)
        angle = 2.0 * np.pi * np.random.rand()
        U_out.add_parametric_RZ_gate(i,angle)
        angle = 2.0 * np.pi * np.random.rand()
        U_out.add_parametric_RX_gate(i,angle)
[16]:
# Get the list of initial values of the parameter theta
parameter_count = U_out.get_parameter_count()
theta_init = [U_out.get_parameter(ind) for ind in range(parameter_count)]
[17]:
theta_init
[17]:
[6.007250646127814,
 4.046309757767312,
 2.663159813474645,
 3.810080933381979,
 0.12059442161498848,
 1.8948504571449056,
 4.14799267096281,
 1.8226113595664735,
 3.88310546309581,
 2.6940332019609157,
 0.851208649826403,
 1.8741631278382846,
 3.5811951525261123,
 3.7125630518871535,
 3.6085919651139333,
 4.104181793964002,
 4.097285684838374,
 2.71068197476515,
 5.633168398253273,
 2.309459341364396,
 2.738620094343915,
 5.6041197193647925,
 5.065466226710866,
 4.4226624059922806,
 0.6297441057449945,
 5.777279648887616,
 4.487710439107831]

For convenience, a function for updating parameter \(\theta\) in \(U(\theta)\) is created.

[18]:
# Function that updates parameter theta
def set_U_out(theta):
    global U_out

    parameter_count = U_out.get_parameter_count()

    for i in range(parameter_count):
        U_out.set_parameter(i, theta[i])
Measurement

In this demonstration, the output of the model is the expectation value of 0th qubit’s Pauli Z on output state \(\left|\psi_\text{out}\right>\), that is:

\begin{equation} y(\theta,x_i)=\left<Z_0\right>=\left<\psi_\text{out}|Z_0|\psi_\text{out}\right> \end{equation}
[19]:
# Create observable Z_0
from qulacs import Observable
obs = Observable(nqubit)
obs.add_operator(2.,'Z 0')
# Set observable as 2*Z。
# The reason for multiplying by 2 here is to expand the value range of the final <Z>.
# In order to cope with any unknown function, this constant also needs to be optimized as one parameter.
[20]:
obs.get_expectation_value(state)
[20]:
1.9899748742132415
Combine a series of procedures into one function

The procedures up to this point can be combined to define a function that returns the predicted value \(y(x_i,\theta)\) of the model from the input \(x_i\).

[21]:
# Function that gives prediction value y(x_i, theta) of the model from input x_i
def qcl_pred(x, U_out):
    state = QuantumState(nqubit)
    state.set_zero_state()

    # Calculate input state
    U_in(x).update_quantum_state(state)

    # Calculate output state
    U_out.update_quantum_state(state)

    # Output of the model
    res = obs.get_expectation_value(state)

    return res
Calculation of cost function

The cost function \(L(\theta)\) is a mean square error (MSE) between the teacher data and the prediction data.

[22]:
# Calculate cost function L
def cost_func(theta):
    '''
    theta: ndarray of length c_depth * nqubit * 3
    '''
    # update the parameter theta of U_out
    # global U_out
    set_U_out(theta)

    # calculate basing on data of num_x_train in total
    y_pred = [qcl_pred(x, U_out) for x in x_train]

    # quadratic loss
    L = ((y_pred - y_train)**2).mean()

    return L
[23]:
# Value of cost function with initial parameter theta
cost_func(theta_init)
[23]:
1.38892593161935
[24]:
# Figure basing on inital parameter theta
xlist = np.arange(x_min, x_max, 0.02)
y_init = [qcl_pred(x, U_out) for x in xlist]
plt.plot(xlist, y_init)
[24]:
[<matplotlib.lines.Line2D at 0x11e0de090>]
_images/apply_5.2_qcl_34_1.png
Learning (optimization by scipy.optimize.minimize)

Preparation is finally finished, and let’s start learning from now on. Here, for simplicity, optimization is performed using the Nelder-Mead method, which does not need a gradient calculation formula. When using an optimization method that needs gradients (eg: the BFGS method), refer to the useful gradients calculation formulas introduced in Reference [1].

[25]:
from scipy.optimize import minimize
[26]:
%%time
# Learning (takes 14 seconds with the writer's PC)
result = minimize(cost_func, theta_init, method='Nelder-Mead')
CPU times: user 11.7 s, sys: 11.7 s, total: 23.4 s
Wall time: 14.2 s
[27]:
# Value of cost_function after optimization
result.fun
[27]:
0.003987076559624772
[28]:
# Solution of theta by optimization
theta_opt = result.x
print(theta_opt)
[7.17242144 5.4043736  1.27744316 3.09192904 0.13144047 2.13757354
 4.58470259 2.01924008 2.96107066 2.91843537 1.0609229  1.70351774
 6.41114609 6.25686828 2.41619471 3.69387805 4.07551328 1.47666316
 3.4108701  2.28524042 1.75253621 7.44181397 3.20314179 5.11364648
 1.2831137  2.07306927 3.75112591]
Plot results
[29]:
# Insert optimized theta into U_out
set_U_out(theta_opt)
[30]:
# Plot
plt.figure(figsize=(10, 6))

xlist = np.arange(x_min, x_max, 0.02)

# teacher data
plt.plot(x_train, y_train, "o", label='Teacher')

# Figure basing on inital parameter theta
plt.plot(xlist, y_init, '--', label='Initial Model Prediction', c='gray')

# Prediction of the model
y_pred = np.array([qcl_pred(x, U_out) for x in xlist])
plt.plot(xlist, y_pred, label='Final Model Prediction')

plt.legend()
plt.show()
_images/apply_5.2_qcl_42_0.png

It is clear that the approximation of the sin function was successful.

Here we dealt with a very simple task of a one-dimensional function approximation for both input and output, but it can be extended to approximation and classification problems with multidimensional inputs and outputs.

Motivated readers are encouraged to try to classify the Iris dataset, one of the typical machine learning datasets, in column 5.2c. Application of QCL to Machine Learning.

Reference

[1] K. Mitarai, M. Negoro, M. Kitagawa, and K. Fujii, “Quantum circuit learning”, Phys. Rev. A 98, 032309 (2018), arXiv:https://arxiv.org/abs/1803.00745

[2] V. Havlicek et al. , “Supervised learning with quantum-enhanced feature spaces”, Nature 567, 209–212 (2019), arXiv:https://arxiv.org/abs/1804.11326

Variational Quantum Eigensolver (VQE)

In this section, the variational quantum eigensolver (VQE) is run on the simulator using Qulacs to find the ground state of the quantum chemical Hamiltonian obtained using OpenFermion/PySCF.

This notebook is translated from https://dojo.qulacs.org/ja/latest/notebooks/6.2_qulacs_VQE.html

Necessary packages:

  • qulacs

  • openfermion

  • openfermion-pyscf

  • pyscf

  • scipy

  • numpy

Install and import necessary packages
[2]:
## Please execute if various libraries are not installed
## When use Google Colaboratory, please ignore 'You must restart the runtime in order to use newly installed versions'.
## Crash when restarting runtime.
!pip install qulacs pyscf openfermion openfermionpyscf
[3]:
import qulacs
from openfermion.transforms import get_fermion_operator, jordan_wigner
from openfermion.transforms import get_sparse_operator
from openfermion.hamiltonians import MolecularData
from openfermionpyscf import run_pyscf
from scipy.optimize import minimize
from pyscf import fci
import numpy as np
import matplotlib.pyplot as plt
Create Hamiltonian

Create Hamiltonian by PySCF in the same procedure as described in the previous section.

[4]:
basis = "sto-3g"
multiplicity = 1
charge = 0
distance  = 0.977
geometry = [["H", [0,0,0]],["H", [0,0,distance]]]
description  = "tmp"
molecule = MolecularData(geometry, basis, multiplicity, charge, description)
molecule = run_pyscf(molecule,run_scf=1,run_fci=1)
n_qubit = molecule.n_qubits
n_electron = molecule.n_electrons
fermionic_hamiltonian = get_fermion_operator(molecule.get_molecular_hamiltonian())
jw_hamiltonian = jordan_wigner(fermionic_hamiltonian)
Convert Hamiltonian to qulacs Hamiltonian

In Qulacs, observables like Hamiltonians are handled by the Observable class. There is a function create_observable_from_openfermion_text that converts OpenFermion Hamiltonian to Qulacs Observable.

[5]:
from qulacs import Observable
from qulacs.observable import create_observable_from_openfermion_text
qulacs_hamiltonian = create_observable_from_openfermion_text(str(jw_hamiltonian))
Construct ansatz

Construct a quantum circuit on Qulacs. Here, the quantum circuit is modeled after the experiments with superconducting qubits (A. Kandala et. al. , “Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets“, Nature 549, 242–246).

[6]:
from qulacs import QuantumState, QuantumCircuit
from qulacs.gate import CZ, RY, RZ, merge

depth = n_qubit
[7]:
def he_ansatz_circuit(n_qubit, depth, theta_list):
    """he_ansatz_circuit
    Returns hardware efficient ansatz circuit.

    Args:
        n_qubit (:class:`int`):
            the number of qubit used (equivalent to the number of fermionic modes)
        depth (:class:`int`):
            depth of the circuit.
        theta_list (:class:`numpy.ndarray`):
            rotation angles.
    Returns:
        :class:`qulacs.QuantumCircuit`
    """
    circuit = QuantumCircuit(n_qubit)
    for d in range(depth):
        for i in range(n_qubit):
            circuit.add_gate(merge(RY(i, theta_list[2*i+2*n_qubit*d]), RZ(i, theta_list[2*i+1+2*n_qubit*d])))
        for i in range(n_qubit//2):
            circuit.add_gate(CZ(2*i, 2*i+1))
        for i in range(n_qubit//2-1):
            circuit.add_gate(CZ(2*i+1, 2*i+2))
    for i in range(n_qubit):
        circuit.add_gate(merge(RY(i, theta_list[2*i+2*n_qubit*depth]), RZ(i, theta_list[2*i+1+2*n_qubit*depth])))

    return circuit
Define VQE cost function

As explained in Section 5-1, VQE obtains an approximate ground state by minimizing the expected value

\begin{equation} \left<H(\theta)\right>=\left<\psi(\theta)|H|\psi(\theta)\right> \end{equation}

of Hamiltonian for state \(\left|\psi(\theta)\right>=U(\theta)\left|0\right>\) output from the quantum circuit \(U(\theta)\) with parameters. The following defines a function that returns the expectation value of this Hamiltonian.

[12]:
def cost(theta_list):
    state = QuantumState(n_qubit) #Prepare |00000>
    circuit = he_ansatz_circuit(n_qubit, depth, theta_list) #Construct quantum circuit
    circuit.update_quantum_state(state) #Operate quantum circuit on state
    return qulacs_hamiltonian.get_expectation_value(state) #Calculate expectation value of Hamiltonian
Run VQE

Now everthing is prepared, run VQE. For optimization, the BFGS method implemented in scipy is applied, and initial parameters are randomly selected. This process should end in tens of seconds.

[9]:
cost_history = []
init_theta_list = np.random.random(2*n_qubit*(depth+1))*1e-1
cost_history.append(cost(init_theta_list))
method = "BFGS"
options = {"disp": True, "maxiter": 50, "gtol": 1e-6}
opt = minimize(cost, init_theta_list,
               method=method,
               callback=lambda x: cost_history.append(cost(x)))

The results can be plotted to see that they converge to the correct solution.

[10]:
plt.rcParams["font.size"] = 18
plt.plot(cost_history, color="red", label="VQE")
plt.plot(range(len(cost_history)), [molecule.fci_energy]*len(cost_history), linestyle="dashed", color="black", label="Exact Solution")
plt.xlabel("Iteration")
plt.ylabel("Energy expectation value")
plt.legend()
plt.show()
_images/apply_6.2_vqe_15_0.png

If you are interested, you can calculate the ground state by varying the distance between hydrogen atoms to find the interatomic distance at which the hydrogen molecule is most stable. (It should be about 0.74 angstroms, depending on the performance of the ansatz.)

Subspace-Search Variational Quantum Eigensolver

As explained in section 5-1, the variational quantum eigensolver (VQE) is an algorithm for searching the ground state of a quantum system. The ground state is an important state that determines the properties of various substances, but there are also phenomena such as photoresponse that are difficult to describe without the excited states.

Therefore, algorithms for generating a wave function of an excited state on a quantum computer have been actively studied. Among them, here a new method proposed in 2018, Subspace-Search VQE (SSVQE) [1] is introduced.

This notebook is translated from https://dojo.qulacs.org/ja/latest/notebooks/6.3_subspace_search_VQE.html

Algorithnm

The procedures for SSVQE is as following:

  1. Prepare \(k\) initial states \(\{\left|\varphi_i\right>\}_{i=0}^{k-1}\) orthogonal to each other.

  2. For each of them, operate an appropriate quantum circuit \(U(\theta)\) to generate a trial state. (Note: \(\left|\psi_i(\theta)\right>=U(\theta)\left|\varphi_i\right>\))

  3. Adjust \(\theta\) to minimize cost function \(L(\theta)=\sum_i w_i \left<\psi_i(\theta)\left|H\right|\psi_i(\theta)\right>\). Here when \(w_i\) is positive and \(i>j\), make sure \(w_i<w_j\).

When \(U(\theta)\) has sufficient expressiveness, \(\left|\psi_i(\theta)\right>\) becomes the \(i\)th excited state at converged \(\theta\). This is because when the \(i\)th excited state of the Hamiltonian is \(\left|E_i\right>\), the global minimum of the cost function is \(\left|\psi_i\right>=\left|E_i\right>\). (Refer to the original paper [1] for details)

The following shows an example of simulating SSVQE using Qulacs.

Implementation of SSVQE

Implement SSVQE to search ground state and first excited state of hydrogen molecule. When hydrogen molecule is treated with sto-3g minimal basis set, 4 qubit Hamiltonian can be obtained. Therefore, two initial states, \(\left|0000\right>\) and \(\left|0001\right>\), which are flipped by one qubit, are used as orthogonal initial states required for SSVQE.

  • Note for those who are familiar with quantum chemistry: The first excited state here is the first excited state of the Hamiltonian of a hydrogen molecule without considering the number of electrons, and in chemistry terms, the ground state of a hydrogen molecular ion.

Create Hamiltonian

Follow the same procedure as explained before to calculate Hamiltonian using PySCF + OpenFermion. However, the excited state is considered in SSVQE, so scipy.sparse.linalg.eigsh is used to obtain the exact solution of excited state.

[ ]:
## Please execute if various libraries are not installed
## When use Google Colaboratory, please ignore 'You must restart the runtime in order to use newly installed versions'.
## Crash when restarting runtime.
!pip install qulacs pyscf openfermion openfermionpyscf
[1]:
import qulacs
from openfermion.transforms import get_fermion_operator, jordan_wigner
from openfermion.transforms import get_sparse_operator
from openfermion.hamiltonians import MolecularData
from openfermionpyscf import run_pyscf
from scipy.optimize import minimize
from pyscf import fci
import numpy as np
import matplotlib.pyplot as plt
[2]:
basis = "sto-3g"
multiplicity = 1
charge = 0
distance  = 0.977
geometry = [["H", [0,0,0]],["H", [0,0,distance]]]
description  = "tmp"
molecule = MolecularData(geometry, basis, multiplicity, charge, description)
molecule = run_pyscf(molecule,run_scf=1,run_fci=1)
n_qubit = molecule.n_qubits
n_electron = molecule.n_electrons
fermionic_hamiltonian = get_fermion_operator(molecule.get_molecular_hamiltonian())
jw_hamiltonian = jordan_wigner(fermionic_hamiltonian)
hamiltonian_matrix = get_sparse_operator(jw_hamiltonian)
from scipy.sparse.linalg import eigsh
eigval, eigvec = eigsh(hamiltonian_matrix, k=2, which="SA")
from qulacs import Observable
from qulacs.observable import create_observable_from_openfermion_text
qulacs_hamiltonian = create_observable_from_openfermion_text(str(jw_hamiltonian))
Construct ansatz

Create quantum circuit on Qulacs. Here, the quantum circuit is modeled after the experiments with superconducting qubits (A. Kandala et. al. , “Hardware-efficient variational quantum eigensolver for small molecules and quantum magnets“, Nature 549, 242–246).

[3]:
from qulacs import QuantumState, QuantumCircuit
from qulacs.gate import CZ, RY, RZ, merge

depth = n_qubit
[4]:
def he_ansatz_circuit(n_qubit, depth, theta_list):
    """he_ansatz_circuit
    Returns hardware efficient ansatz circuit.

    Args:
        n_qubit (:class:`int`):
            the number of qubit used (equivalent to the number of fermionic modes)
        depth (:class:`int`):
            depth of the circuit.
        theta_list (:class:`numpy.ndarray`):
            rotation angles.
    Returns:
        :class:`qulacs.QuantumCircuit`
    """
    circuit = QuantumCircuit(n_qubit)
    circuit.add_gate(RY(0, theta_list[-2]))
    circuit.add_gate(RZ(0, theta_list[-1]))
    for d in range(depth):
        for i in range(n_qubit):
            circuit.add_gate(merge(RY(i, theta_list[2*i+2*n_qubit*d]), RZ(i, theta_list[2*i+1+2*n_qubit*d])))
        for i in range(n_qubit//2):
            circuit.add_gate(CZ(2*i, 2*i+1))
        for i in range(n_qubit//2-1):
            circuit.add_gate(CZ(2*i+1, 2*i+2))
    for i in range(n_qubit):
        circuit.add_gate(merge(RY(i, theta_list[2*i+2*n_qubit*depth]), RZ(i, theta_list[2*i+1+2*n_qubit*depth])))

    return circuit
Define cost function of SSVQE
[5]:
def get_exp(state, theta_list):
    circuit = he_ansatz_circuit(n_qubit, depth, theta_list) #Create quantum circuit
    circuit.update_quantum_state(state) #Operate on quantum state
    return qulacs_hamiltonian.get_expectation_value(state)

def cost(theta_list):
    state0 = QuantumState(n_qubit) #Prepare |00000>
    state1 = QuantumState(n_qubit); state1.set_computational_basis(1) #Prepare |00001>
    return get_exp(state0, theta_list)+0.5*get_exp(state1, theta_list)

init_theta_list = np.random.random(2*n_qubit*(depth+1)+2)*1e-1
cost(init_theta_list)
[5]:
0.21631044919594045
Run SSVQE

Now everthing is prepared, run SSVQE. For optimization, the BFGS method implemented in scipy is applied, and initial parameters are randomly selected. This process should end in tens of seconds.

[6]:
exp_history0 = []
exp_history1 = []
def callback(theta_list):
    state0 = QuantumState(n_qubit) #Prepare |0000>
    state1 = QuantumState(n_qubit); state1.set_computational_basis(1) #Prepare |0001>
    exp_history0.append(get_exp(state0, theta_list))
    exp_history1.append(get_exp(state1, theta_list))
init_theta_list = np.random.random(2*n_qubit*(depth+1)+2)*1e-1
method = "BFGS"
options = {"disp": True, "maxiter": 50, "gtol": 1e-6}
opt = minimize(cost, init_theta_list,
               method=method,
               callback=callback)

The results can be plotted to see that they converge to the correct solution.

[7]:
plt.rcParams["font.size"] = 18
plt.plot(exp_history0, label=r"input $|0000\rangle$")
plt.plot(exp_history1, label=r"input $|0001\rangle$")
plt.plot(range(len(exp_history0)), [molecule.fci_energy]*len(exp_history0), linestyle="dashed", color="black", label="Exact ground state energy")
plt.plot(range(len(exp_history1)), [eigval[1]]*len(exp_history1), linestyle="-.", color="black", label="Exact 1st excited state energy")
plt.xlabel("Iteration")
plt.ylabel("Energy expectation value")
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0, fontsize=18)
plt.show()
_images/apply_6.3_ssvqe_12_0.png
Reference

[1] K. M Nakanishi, K. Mitarai, and K. Fujii, “Subspace-search variational quantum eigensolver for excited states”, Phys. Rev. Research 1, 033062 (2019), https://arxiv.org/abs/1810.09434

[ ]:

Python API Reference

qulacs

cppsim python interface

class qulacs_core.CausalConeSimulator

Bases: pybind11_builtins.pybind11_object

build(self: qulacs_core.CausalConeSimulator) None

Build

get_circuit_list(self: qulacs_core.CausalConeSimulator) List[List[qulacs_core.ParametricQuantumCircuit]]

Return circuit_list

get_coef_list(self: qulacs_core.CausalConeSimulator) List[complex]

Return coef_list

get_expectation_value(self: qulacs_core.CausalConeSimulator) complex

Return expectation_value

get_pauli_operator_list(self: qulacs_core.CausalConeSimulator) List[List[qulacs_core.PauliOperator]]

Return pauli_operator_list

class qulacs_core.ClsNoisyEvolution

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsNoisyEvolution_fast

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsOneControlOneTargetGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsOneQubitGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsOneQubitRotationGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsPauliGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsPauliRotationGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsReversibleBooleanGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsStateReflectionGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.ClsTwoQubitGate

Bases: qulacs_core.QuantumGateBase

class qulacs_core.DensityMatrix

Bases: qulacs_core.QuantumStateBase

add_state(self: qulacs_core.DensityMatrix, state: qulacs_core.QuantumStateBase) None

Add state vector to this state

allocate_buffer(self: qulacs_core.DensityMatrix) qulacs_core.DensityMatrix

Allocate buffer with the same size

copy(self: qulacs_core.DensityMatrix) qulacs_core.DensityMatrix

Create copied insntace

get_classical_value(self: qulacs_core.DensityMatrix, index: int) int

Get classical value

get_device_name(self: qulacs_core.DensityMatrix) str

Get allocated device name

get_entropy(self: qulacs_core.DensityMatrix) float

Get entropy

get_marginal_probability(self: qulacs_core.DensityMatrix, measured_values: List[int]) float

Get merginal probability for measured values

get_matrix(self: qulacs_core.DensityMatrix) numpy.ndarray[numpy.complex128[m, n]]

Get density matrix

get_qubit_count(self: qulacs_core.DensityMatrix) int

Get qubit count

get_squared_norm(self: qulacs_core.DensityMatrix) float

Get squared norm

get_zero_probability(self: qulacs_core.DensityMatrix, index: int) float

Get probability with which we obtain 0 when we measure a qubit

load(*args, **kwargs)

Overloaded function.

  1. load(self: qulacs_core.DensityMatrix, state: qulacs_core.QuantumStateBase) -> None

Load quantum state vector or density matrix

  1. load(self: qulacs_core.DensityMatrix, state: List[complex]) -> None

  2. load(self: qulacs_core.DensityMatrix, state: numpy.ndarray[numpy.complex128[m, n]]) -> None

multiply_coef(self: qulacs_core.DensityMatrix, coef: complex) None

Multiply coefficient to this state

normalize(self: qulacs_core.DensityMatrix, squared_norm: float) None

Normalize quantum state

sampling(*args, **kwargs)

Overloaded function.

  1. sampling(self: qulacs_core.DensityMatrix, sampling_count: int) -> List[int]

Sampling measurement results

  1. sampling(self: qulacs_core.DensityMatrix, sampling_count: int, random_seed: int) -> List[int]

set_Haar_random_state(*args, **kwargs)

Overloaded function.

  1. set_Haar_random_state(self: qulacs_core.DensityMatrix) -> None

Set Haar random state

  1. set_Haar_random_state(self: qulacs_core.DensityMatrix, seed: int) -> None

set_classical_value(self: qulacs_core.DensityMatrix, index: int, value: int) None

Set classical value

set_computational_basis(self: qulacs_core.DensityMatrix, comp_basis: int) None

Set state to computational basis

set_zero_state(self: qulacs_core.DensityMatrix) None

Set state to |0>

to_json(self: qulacs_core.DensityMatrix) str

to json string

to_string(self: qulacs_core.DensityMatrix) str

to string

class qulacs_core.GeneralQuantumOperator

Bases: pybind11_builtins.pybind11_object

add_operator(*args, **kwargs)

Overloaded function.

  1. add_operator(self: qulacs_core.GeneralQuantumOperator, pauli_operator: qulacs_core.PauliOperator) -> None

Add Pauli operator

  1. add_operator(self: qulacs_core.GeneralQuantumOperator, coef: complex, pauli_string: str) -> None

add_operator_copy(self: qulacs_core.GeneralQuantumOperator, pauli_operator: qulacs_core.PauliOperator) None

Add Pauli operator

add_operator_move(self: qulacs_core.GeneralQuantumOperator, pauli_operator: qulacs_core.PauliOperator) None

Add Pauli operator

apply_to_state(*args, **kwargs)

Overloaded function.

  1. apply_to_state(self: qulacs_core.GeneralQuantumOperator, work_state: QuantumStateBase, state_to_be_multiplied: QuantumStateBase, dst_state: QuantumStateBase) -> None

Apply observable to state_to_be_multiplied. The result is stored into dst_state.

  1. apply_to_state(self: qulacs_core.GeneralQuantumOperator, state_to_be_multiplied: QuantumStateBase, dst_state: QuantumStateBase) -> None

copy(self: qulacs_core.GeneralQuantumOperator) qulacs_core.GeneralQuantumOperator

Create copied instance of General Quantum operator class

get_expectation_value(self: qulacs_core.GeneralQuantumOperator, state: QuantumStateBase) complex

Get expectation value

get_expectation_value_single_thread(self: qulacs_core.GeneralQuantumOperator, state: QuantumStateBase) complex

Get expectation value

get_matrix()
get_qubit_count(self: qulacs_core.GeneralQuantumOperator) int

Get qubit count

get_state_dim(self: qulacs_core.GeneralQuantumOperator) int

Get state dimension

get_term(self: qulacs_core.GeneralQuantumOperator, index: int) qulacs_core.PauliOperator

Get Pauli term

get_term_count(self: qulacs_core.GeneralQuantumOperator) int

Get count of Pauli terms

get_transition_amplitude(self: qulacs_core.GeneralQuantumOperator, state_bra: QuantumStateBase, state_ket: QuantumStateBase) complex

Get transition amplitude

is_hermitian(self: qulacs_core.GeneralQuantumOperator) bool

Get is Herimitian

to_json(self: qulacs_core.GeneralQuantumOperator) str

to json string

class qulacs_core.GradCalculator

Bases: pybind11_builtins.pybind11_object

calculate_grad(*args, **kwargs)

Overloaded function.

  1. calculate_grad(self: qulacs_core.GradCalculator, parametric_circuit: qulacs_core.ParametricQuantumCircuit, observable: qulacs_core.Observable) -> List[complex]

Calculate Grad

  1. calculate_grad(self: qulacs_core.GradCalculator, parametric_circuit: qulacs_core.ParametricQuantumCircuit, observable: qulacs_core.Observable, angles_of_gates: List[float]) -> List[complex]

class qulacs_core.NoiseSimulator

Bases: pybind11_builtins.pybind11_object

execute(self: qulacs_core.NoiseSimulator, arg0: int) List[int]

Sampling & Return result [array]

execute_and_get_result(self: qulacs_core.NoiseSimulator, arg0: int) qulacs_core.SimulationResult

Simulate & Return ressult [array of (state, frequency)]

class qulacs_core.Observable

Bases: qulacs_core.GeneralQuantumOperator

add_operator(*args, **kwargs)

Overloaded function.

  1. add_operator(self: qulacs_core.Observable, pauli_operator: qulacs_core.PauliOperator) -> None

Add Pauli operator

  1. add_operator(self: qulacs_core.Observable, coef: complex, string: str) -> None

add_operator_copy(self: qulacs_core.Observable, pauli_operator: qulacs_core.PauliOperator) None

Add Pauli operator

add_operator_move(self: qulacs_core.Observable, pauli_operator: qulacs_core.PauliOperator) None

Add Pauli operator

add_random_operator(*args, **kwargs)

Overloaded function.

  1. add_random_operator(self: qulacs_core.Observable, operator_count: int) -> None

Add random pauli operator

  1. add_random_operator(self: qulacs_core.Observable, operator_count: int, seed: int) -> None

apply_to_state(self: qulacs_core.Observable, work_state: QuantumStateBase, state_to_be_multiplied: QuantumStateBase, dst_state: QuantumStateBase) None

Apply observable to state_to_be_multiplied. The result is stored into dst_state.

get_expectation_value(self: qulacs_core.Observable, state: QuantumStateBase) float

Get expectation value

get_expectation_value_single_thread(self: qulacs_core.Observable, state: QuantumStateBase) float

Get expectation value

get_matrix()
get_qubit_count(self: qulacs_core.Observable) int

Get qubit count

get_state_dim(self: qulacs_core.Observable) int

Get state dimension

get_term(self: qulacs_core.Observable, index: int) qulacs_core.PauliOperator

Get Pauli term

get_term_count(self: qulacs_core.Observable) int

Get count of Pauli terms

get_transition_amplitude(self: qulacs_core.Observable, state_bra: QuantumStateBase, state_ket: QuantumStateBase) complex

Get transition amplitude

solve_ground_state_eigenvalue_by_arnoldi_method(self: qulacs_core.Observable, state: QuantumStateBase, iter_count: int, mu: complex = 0.0) complex

Compute ground state eigenvalue by arnoldi method

solve_ground_state_eigenvalue_by_lanczos_method(self: qulacs_core.Observable, state: QuantumStateBase, iter_count: int, mu: complex = 0.0) complex

Compute ground state eigenvalue by lanczos method

solve_ground_state_eigenvalue_by_power_method(self: qulacs_core.Observable, state: QuantumStateBase, iter_count: int, mu: complex = 0.0) complex

Compute ground state eigenvalue by power method

class qulacs_core.ParametricQuantumCircuit

Bases: qulacs_core.QuantumCircuit

add_gate(*args, **kwargs)

Overloaded function.

  1. add_gate(self: qulacs_core.ParametricQuantumCircuit, gate: qulacs_core.QuantumGateBase) -> None

Add gate

  1. add_gate(self: qulacs_core.ParametricQuantumCircuit, gate: qulacs_core.QuantumGateBase, position: int) -> None

add_parametric_RX_gate(self: qulacs_core.ParametricQuantumCircuit, index: int, angle: float) None

Add parametric Pauli-X rotation gate

add_parametric_RY_gate(self: qulacs_core.ParametricQuantumCircuit, index: int, angle: float) None

Add parametric Pauli-Y rotation gate

add_parametric_RZ_gate(self: qulacs_core.ParametricQuantumCircuit, index: int, angle: float) None

Add parametric Pauli-Z rotation gate

add_parametric_gate(*args, **kwargs)

Overloaded function.

  1. add_parametric_gate(self: qulacs_core.ParametricQuantumCircuit, gate: qulacs_core.QuantumGate_SingleParameter) -> None

Add parametric gate

  1. add_parametric_gate(self: qulacs_core.ParametricQuantumCircuit, gate: qulacs_core.QuantumGate_SingleParameter, position: int) -> None

add_parametric_multi_Pauli_rotation_gate(self: qulacs_core.ParametricQuantumCircuit, index_list: List[int], pauli_ids: List[int], angle: float) None

Add parametric multi-qubit Pauli rotation gate

backprop(self: qulacs_core.ParametricQuantumCircuit, obs: qulacs_core.GeneralQuantumOperator) List[float]

Do backprop

backprop_inner_product(self: qulacs_core.ParametricQuantumCircuit, state: qulacs_core.QuantumState) List[float]

Do backprop with innder product

copy(self: qulacs_core.ParametricQuantumCircuit) qulacs_core.ParametricQuantumCircuit

Create copied instance

get_parameter(self: qulacs_core.ParametricQuantumCircuit, index: int) float

Get parameter

get_parameter_count(self: qulacs_core.ParametricQuantumCircuit) int

Get parameter count

get_parametric_gate_position(self: qulacs_core.ParametricQuantumCircuit, index: int) int

Get parametric gate position

merge_circuit(self: qulacs_core.ParametricQuantumCircuit, circuit: qulacs_core.ParametricQuantumCircuit) None

Merge another ParametricQuantumCircuit

remove_gate(self: qulacs_core.ParametricQuantumCircuit, position: int) None

Remove gate

set_parameter(self: qulacs_core.ParametricQuantumCircuit, index: int, parameter: float) None

Set parameter

class qulacs_core.PauliOperator

Bases: pybind11_builtins.pybind11_object

add_single_Pauli(self: qulacs_core.PauliOperator, index: int, pauli_type: int) None

Add Pauli operator to this term

change_coef(self: qulacs_core.PauliOperator, new_coef: complex) None

Change coefficient

copy(self: qulacs_core.PauliOperator) qulacs_core.PauliOperator

Create copied instance of Pauli operator class

get_coef(self: qulacs_core.PauliOperator) complex

Get coefficient of Pauli term

get_expectation_value(self: qulacs_core.PauliOperator, state: QuantumStateBase) complex

Get expectation value

get_expectation_value_single_thread(self: qulacs_core.PauliOperator, state: QuantumStateBase) complex

Get expectation value

get_index_list(self: qulacs_core.PauliOperator) List[int]

Get list of target qubit indices

get_pauli_id_list(self: qulacs_core.PauliOperator) List[int]

Get list of Pauli IDs (I,X,Y,Z) = (0,1,2,3)

get_pauli_string(self: qulacs_core.PauliOperator) str

Get pauli string

get_transition_amplitude(self: qulacs_core.PauliOperator, state_bra: QuantumStateBase, state_ket: QuantumStateBase) complex

Get transition amplitude

class qulacs_core.QuantumCircuit

Bases: pybind11_builtins.pybind11_object

add_CNOT_gate(self: qulacs_core.QuantumCircuit, control: int, target: int) None

Add CNOT gate

add_CZ_gate(self: qulacs_core.QuantumCircuit, control: int, target: int) None

Add CNOT gate

add_H_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add Hadamard gate

add_P0_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add projection gate to |0> subspace

add_P1_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add projection gate to |1> subspace

add_RX_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-X rotation gate

add_RY_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-Y rotation gate

add_RZ_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-Z rotation gate

add_RotInvX_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-X rotation gate

add_RotInvY_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-Y rotation gate

add_RotInvZ_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-Z rotation gate

add_RotX_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-X rotation gate

add_RotY_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-Y rotation gate

add_RotZ_gate(self: qulacs_core.QuantumCircuit, index: int, angle: float) None

Add Pauli-Z rotation gate

add_SWAP_gate(self: qulacs_core.QuantumCircuit, target1: int, target2: int) None

Add SWAP gate

add_S_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add pi/4 phase gate

add_Sdag_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add adjoint of pi/4 phsae gate

add_T_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add pi/8 phase gate

add_Tdag_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add adjoint of pi/8 phase gate

add_U1_gate(self: qulacs_core.QuantumCircuit, index: int, lambda_: float) None

Add QASM U1 gate

add_U2_gate(self: qulacs_core.QuantumCircuit, index: int, phi: float, lambda_: float) None

Add QASM U2 gate

add_U3_gate(self: qulacs_core.QuantumCircuit, index: int, theta: float, phi: float, lambda_: float) None

Add QASM U3 gate

add_X_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add Pauli-X gate

add_Y_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add Pauli-Y gate

add_Z_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add Pauli-Z gate

add_dense_matrix_gate(*args, **kwargs)

Overloaded function.

  1. add_dense_matrix_gate(self: qulacs_core.QuantumCircuit, index: int, matrix: numpy.ndarray[numpy.complex128[m, n]]) -> None

Add dense matrix gate

  1. add_dense_matrix_gate(self: qulacs_core.QuantumCircuit, index_list: List[int], matrix: numpy.ndarray[numpy.complex128[m, n]]) -> None

add_diagonal_observable_rotation_gate(self: qulacs_core.QuantumCircuit, observable: qulacs_core.Observable, angle: float) None

Add diagonal observable rotation gate

add_gate(*args, **kwargs)

Overloaded function.

  1. add_gate(self: qulacs_core.QuantumCircuit, gate: qulacs_core.QuantumGateBase) -> None

Add gate with copy

  1. add_gate(self: qulacs_core.QuantumCircuit, gate: qulacs_core.QuantumGateBase, position: int) -> None

add_multi_Pauli_gate(*args, **kwargs)

Overloaded function.

  1. add_multi_Pauli_gate(self: qulacs_core.QuantumCircuit, index_list: List[int], pauli_ids: List[int]) -> None

Add multi-qubit Pauli gate

  1. add_multi_Pauli_gate(self: qulacs_core.QuantumCircuit, pauli: qulacs_core.PauliOperator) -> None

add_multi_Pauli_rotation_gate(*args, **kwargs)

Overloaded function.

  1. add_multi_Pauli_rotation_gate(self: qulacs_core.QuantumCircuit, index_list: List[int], pauli_ids: List[int], angle: float) -> None

Add multi-qubit Pauli rotation gate

  1. add_multi_Pauli_rotation_gate(self: qulacs_core.QuantumCircuit, pauli: qulacs_core.PauliOperator) -> None

add_noise_gate(self: qulacs_core.QuantumCircuit, gate: qulacs_core.QuantumGateBase, NoiseType: str, NoiseProbability: float) None

Add noise gate with copy

add_observable_rotation_gate(self: qulacs_core.QuantumCircuit, observable: qulacs_core.Observable, angle: float, repeat: int) None

Add observable rotation gate

add_random_unitary_gate(*args, **kwargs)

Overloaded function.

  1. add_random_unitary_gate(self: qulacs_core.QuantumCircuit, index_list: List[int]) -> None

Add random unitary gate

  1. add_random_unitary_gate(self: qulacs_core.QuantumCircuit, index_list: List[int], seed: int) -> None

add_sqrtX_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add pi/4 Pauli-X rotation gate

add_sqrtXdag_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add adjoint of pi/4 Pauli-X rotation gate

add_sqrtY_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add pi/4 Pauli-Y rotation gate

add_sqrtYdag_gate(self: qulacs_core.QuantumCircuit, index: int) None

Add adjoint of pi/4 Pauli-Y rotation gate

calculate_depth(self: qulacs_core.QuantumCircuit) int

Calculate depth of circuit

copy(self: qulacs_core.QuantumCircuit) qulacs_core.QuantumCircuit

Create copied instance

get_gate(self: qulacs_core.QuantumCircuit, position: int) qulacs_core.QuantumGateBase

Get gate instance

get_gate_count(self: qulacs_core.QuantumCircuit) int

Get gate count

get_inverse(self: qulacs_core.QuantumCircuit) qulacs_core.QuantumCircuit

get inverse circuit

get_qubit_count(self: qulacs_core.QuantumCircuit) int

Get qubit count

merge_circuit(self: qulacs_core.QuantumCircuit, circuit: qulacs_core.QuantumCircuit) None
remove_gate(self: qulacs_core.QuantumCircuit, position: int) None

Remove gate

to_json(self: qulacs_core.QuantumCircuit) str
to_string(self: qulacs_core.QuantumCircuit) str

Get string representation

update_quantum_state(*args, **kwargs)

Overloaded function.

  1. update_quantum_state(self: qulacs_core.QuantumCircuit, state: qulacs_core.QuantumStateBase) -> None

Update quantum state

  1. update_quantum_state(self: qulacs_core.QuantumCircuit, state: qulacs_core.QuantumStateBase, start: int, end: int) -> None

class qulacs_core.QuantumCircuitSimulator

Bases: pybind11_builtins.pybind11_object

copy_state_from_buffer(self: qulacs_core.QuantumCircuitSimulator) None

Copy buffer to state

copy_state_to_buffer(self: qulacs_core.QuantumCircuitSimulator) None

Copy state to buffer

get_expectation_value(self: qulacs_core.QuantumCircuitSimulator, observable: qulacs_core.Observable) complex

Get expectation value

get_gate_count(self: qulacs_core.QuantumCircuitSimulator) int

Get gate count

initialize_random_state(*args, **kwargs)

Overloaded function.

  1. initialize_random_state(self: qulacs_core.QuantumCircuitSimulator) -> None

Initialize state with random pure state

  1. initialize_random_state(self: qulacs_core.QuantumCircuitSimulator, seed: int) -> None

initialize_state(self: qulacs_core.QuantumCircuitSimulator, arg0: int) None

Initialize state

simulate(self: qulacs_core.QuantumCircuitSimulator) None

Simulate circuit

simulate_range(self: qulacs_core.QuantumCircuitSimulator, start: int, end: int) None

Simulate circuit

swap_state_and_buffer(self: qulacs_core.QuantumCircuitSimulator) None

Swap state and buffer

class qulacs_core.QuantumGateBase

Bases: pybind11_builtins.pybind11_object

copy(self: qulacs_core.QuantumGateBase) qulacs_core.QuantumGateBase

Create copied instance

get_control_index_list(self: qulacs_core.QuantumGateBase) List[int]

Get control qubit index list

get_control_index_value_list(self: qulacs_core.QuantumGateBase) List[Tuple[int, int]]

Get control qubit pair index value list

get_control_value_list(self: qulacs_core.QuantumGateBase) List[int]

Get control qubit value list

get_inverse(self: qulacs_core.QuantumGateBase) qulacs_core.QuantumGateBase

get inverse gate

get_matrix(self: qulacs_core.QuantumGateBase) numpy.ndarray[numpy.complex128[m, n]]

Get gate matrix

get_name(self: qulacs_core.QuantumGateBase) str

Get gate name

get_target_index_list(self: qulacs_core.QuantumGateBase) List[int]

Get target qubit index list

is_Clifford(self: qulacs_core.QuantumGateBase) bool

Check this gate is element of Clifford group

is_Gaussian(self: qulacs_core.QuantumGateBase) bool

Check this gate is element of Gaussian group

is_Pauli(self: qulacs_core.QuantumGateBase) bool

Check this gate is element of Pauli group

is_commute(self: qulacs_core.QuantumGateBase, gate: qulacs_core.QuantumGateBase) bool

Check this gate commutes with a given gate

is_diagonal(self: qulacs_core.QuantumGateBase) bool

Check the gate matrix is diagonal

is_parametric(self: qulacs_core.QuantumGateBase) bool

Check this gate is parametric gate

to_json(self: qulacs_core.QuantumGateBase) str

to json string

to_string(self: qulacs_core.QuantumGateBase) str

to string

update_quantum_state(self: qulacs_core.QuantumGateBase, state: qulacs_core.QuantumStateBase) None

Update quantum state

class qulacs_core.QuantumGateDiagonalMatrix

Bases: qulacs_core.QuantumGateBase

class qulacs_core.QuantumGateMatrix

Bases: qulacs_core.QuantumGateBase

add_control_qubit(self: qulacs_core.QuantumGateMatrix, index: int, control_value: int) None

Add control qubit

multiply_scalar(self: qulacs_core.QuantumGateMatrix, value: complex) None

Multiply scalar value to gate matrix

class qulacs_core.QuantumGateSparseMatrix

Bases: qulacs_core.QuantumGateBase

class qulacs_core.QuantumGate_Adaptive

Bases: qulacs_core.QuantumGateBase

class qulacs_core.QuantumGate_CP

Bases: qulacs_core.QuantumGateBase

get_gate_list(self: qulacs_core.QuantumGate_CP) List[qulacs_core.QuantumGateBase]

get_gate_list

class qulacs_core.QuantumGate_CPTP

Bases: qulacs_core.QuantumGateBase

QuantumGate_Instrument

get_gate_list(self: qulacs_core.QuantumGate_CPTP) List[qulacs_core.QuantumGateBase]

get_gate_list

class qulacs_core.QuantumGate_Probabilistic

Bases: qulacs_core.QuantumGateBase

QuantumGate_ProbabilisticInstrument

get_cumulative_distribution(self: qulacs_core.QuantumGate_Probabilistic) List[float]

get_cumulative_distribution

get_distribution(self: qulacs_core.QuantumGate_Probabilistic) List[float]

get_distribution

get_gate_list(self: qulacs_core.QuantumGate_Probabilistic) List[qulacs_core.QuantumGateBase]

get_gate_list

optimize_ProbablisticGate(self: qulacs_core.QuantumGate_Probabilistic) None

optimize_ProbablisticGate

class qulacs_core.QuantumGate_SingleParameter

Bases: qulacs_core.QuantumGateBase

copy(self: qulacs_core.QuantumGate_SingleParameter) qulacs_core.QuantumGate_SingleParameter

Create copied instance

get_parameter_value(self: qulacs_core.QuantumGate_SingleParameter) float

Get parameter value

set_parameter_value(self: qulacs_core.QuantumGate_SingleParameter, value: float) None

Set parameter value

class qulacs_core.QuantumState

Bases: qulacs_core.QuantumStateBase

add_state(self: qulacs_core.QuantumState, state: qulacs_core.QuantumStateBase) None

Add state vector to this state

allocate_buffer(self: qulacs_core.QuantumState) qulacs_core.QuantumState

Allocate buffer with the same size

copy(self: qulacs_core.QuantumState) qulacs_core.QuantumState

Create copied instance

get_amplitude(self: qulacs_core.QuantumState, comp_basis: int) complex

Get Amplitude of a specified computational basis

get_classical_value(self: qulacs_core.QuantumState, index: int) int

Get classical value

get_device_name(self: qulacs_core.QuantumState) str

Get allocated device name

get_entropy(self: qulacs_core.QuantumState) float

Get entropy

get_marginal_probability(self: qulacs_core.QuantumState, measured_values: List[int]) float

Get merginal probability for measured values

get_qubit_count(self: qulacs_core.QuantumState) int

Get qubit count

get_squared_norm(self: qulacs_core.QuantumState) float

Get squared norm

get_vector(self: qulacs_core.QuantumState) numpy.ndarray[numpy.complex128[m, 1]]

Get state vector

get_zero_probability(self: qulacs_core.QuantumState, index: int) float

Get probability with which we obtain 0 when we measure a qubit

load(*args, **kwargs)

Overloaded function.

  1. load(self: qulacs_core.QuantumState, state: qulacs_core.QuantumStateBase) -> None

Load quantum state vector

  1. load(self: qulacs_core.QuantumState, state: List[complex]) -> None

multiply_coef(self: qulacs_core.QuantumState, coef: complex) None

Multiply coefficient to this state

multiply_elementwise_function(self: qulacs_core.QuantumState, func: Callable[[int], complex]) None

Multiply elementwise function

normalize(self: qulacs_core.QuantumState, squared_norm: float) None

Normalize quantum state

sampling(*args, **kwargs)

Overloaded function.

  1. sampling(self: qulacs_core.QuantumState, sampling_count: int) -> List[int]

Sampling measurement results

  1. sampling(self: qulacs_core.QuantumState, sampling_count: int, random_seed: int) -> List[int]

set_Haar_random_state(*args, **kwargs)

Overloaded function.

  1. set_Haar_random_state(self: qulacs_core.QuantumState) -> None

Set Haar random state

  1. set_Haar_random_state(self: qulacs_core.QuantumState, seed: int) -> None

set_classical_value(self: qulacs_core.QuantumState, index: int, value: int) None

Set classical value

set_computational_basis(self: qulacs_core.QuantumState, comp_basis: int) None

Set state to computational basis

set_zero_state(self: qulacs_core.QuantumState) None

Set state to |0>

to_json(self: qulacs_core.QuantumState) str

to json string

to_string(self: qulacs_core.QuantumState) str

to string

class qulacs_core.QuantumStateBase

Bases: pybind11_builtins.pybind11_object

class qulacs_core.SimulationResult

Bases: pybind11_builtins.pybind11_object

get_count(self: qulacs_core.SimulationResult) int

get state count

get_frequency(self: qulacs_core.SimulationResult, arg0: int) int

get state frequency

get_state(self: qulacs_core.SimulationResult, arg0: int) qulacs_core.QuantumState

get state

qulacs_core.StateVector(arg0: int) qulacs_core.QuantumState

StateVector

qulacs_core.to_general_quantum_operator(gate: qulacs_core.QuantumGateBase, qubits: int, tol: float) qulacs_core.GeneralQuantumOperator

qulacs.state

qulacs_core.state.drop_qubit(state: qulacs_core.QuantumState, target: List[int], projection: List[int]) qulacs_core.QuantumState

Drop qubits from state

qulacs_core.state.from_json(json: str) qulacs_core.QuantumStateBase

from json string

qulacs_core.state.inner_product(state_bra: qulacs_core.QuantumState, state_ket: qulacs_core.QuantumState) complex

Get inner product

qulacs_core.state.make_mixture(prob1: complex, state1: qulacs_core.QuantumStateBase, prob2: complex, state2: qulacs_core.QuantumStateBase) qulacs_core.DensityMatrix

Create a mixed state

qulacs_core.state.make_superposition(coef1: complex, state1: qulacs_core.QuantumState, coef2: complex, state2: qulacs_core.QuantumState) qulacs_core.QuantumState

Create superposition of states

qulacs_core.state.partial_trace(*args, **kwargs)

Overloaded function.

  1. partial_trace(state: qulacs_core.QuantumState, target_traceout: List[int]) -> qulacs_core.DensityMatrix

Take partial trace

  1. partial_trace(state: qulacs_core.DensityMatrix, target_traceout: List[int]) -> qulacs_core.DensityMatrix

qulacs_core.state.permutate_qubit(*args, **kwargs)

Overloaded function.

  1. permutate_qubit(state: qulacs_core.QuantumState, qubit_order: List[int]) -> qulacs_core.QuantumState

Permutate qubits from state

  1. permutate_qubit(state: qulacs_core.DensityMatrix, qubit_order: List[int]) -> qulacs_core.DensityMatrix

qulacs_core.state.tensor_product(*args, **kwargs)

Overloaded function.

  1. tensor_product(state_left: qulacs_core.QuantumState, state_right: qulacs_core.QuantumState) -> qulacs_core.QuantumState

Get tensor product of states

  1. tensor_product(state_left: qulacs_core.DensityMatrix, state_right: qulacs_core.DensityMatrix) -> qulacs_core.DensityMatrix

qulacs.gate

qulacs_core.gate.Adaptive(*args, **kwargs)

Overloaded function.

  1. Adaptive(gate: qulacs_core.QuantumGateBase, condition: Callable[[List[int]], bool]) -> qulacs_core.QuantumGateBase

Create adaptive gate

  1. Adaptive(gate: qulacs_core.QuantumGateBase, condition: Callable[[List[int], int], bool], id: int) -> qulacs_core.QuantumGateBase

qulacs_core.gate.AmplitudeDampingNoise(index: int, prob: float) qulacs_core.QuantumGate_CPTP

Create amplitude damping noise

qulacs_core.gate.BitFlipNoise(index: int, prob: float) qulacs_core.QuantumGate_Probabilistic

Create bit-flip noise

qulacs_core.gate.CNOT(control: int, target: int) qulacs_core.ClsOneControlOneTargetGate

Create CNOT gate

qulacs_core.gate.CP(kraus_list: List[qulacs_core.QuantumGateBase], state_normalize: bool, probability_normalize: bool, assign_zero_if_not_matched: bool) qulacs_core.QuantumGateBase

Create completely-positive map

qulacs_core.gate.CPTP(kraus_list: List[qulacs_core.QuantumGateBase]) qulacs_core.QuantumGateBase

Create completely-positive trace preserving map

qulacs_core.gate.CZ(control: int, target: int) qulacs_core.ClsOneControlOneTargetGate

Create CZ gate

qulacs_core.gate.DenseMatrix(*args, **kwargs)

Overloaded function.

  1. DenseMatrix(index: int, matrix: numpy.ndarray[numpy.complex128[m, n]]) -> qulacs_core.QuantumGateMatrix

Create dense matrix gate

  1. DenseMatrix(index_list: List[int], matrix: numpy.ndarray[numpy.complex128[m, n]]) -> qulacs_core.QuantumGateMatrix

qulacs_core.gate.DephasingNoise(index: int, prob: float) qulacs_core.QuantumGate_Probabilistic

Create dephasing noise

qulacs_core.gate.DepolarizingNoise(index: int, prob: float) qulacs_core.QuantumGate_Probabilistic

Create depolarizing noise

qulacs_core.gate.DiagonalMatrix(index_list: List[int], diagonal_element: numpy.ndarray[numpy.complex128[m, 1]]) qulacs_core.QuantumGateDiagonalMatrix

Create diagonal matrix gate

qulacs_core.gate.FREDKIN(control: int, target1: int, target2: int) qulacs_core.QuantumGateMatrix

Create FREDKIN gate

qulacs_core.gate.H(index: int) qulacs_core.ClsOneQubitGate

Create Hadamard gate

qulacs_core.gate.Identity(index: int) qulacs_core.ClsOneQubitGate

Create identity gate

qulacs_core.gate.IndependentXZNoise(index: int, prob: float) qulacs_core.QuantumGate_Probabilistic

Create independent XZ noise

qulacs_core.gate.Instrument(kraus_list: List[qulacs_core.QuantumGateBase], register: int) qulacs_core.QuantumGateBase

Create instruments

qulacs_core.gate.Measurement(index: int, register: int) qulacs_core.QuantumGate_CPTP

Create measurement gate

qulacs_core.gate.NoisyEvolution(hamiltonian: qulacs_core.Observable, c_ops: List[qulacs_core.GeneralQuantumOperator], time: float, dt: float) qulacs_core.ClsNoisyEvolution

Create noisy evolution

qulacs_core.gate.NoisyEvolution_fast(hamiltonian: qulacs_core.Observable, c_ops: List[qulacs_core.GeneralQuantumOperator], time: float) qulacs_core.ClsNoisyEvolution_fast

Create noisy evolution fast version

qulacs_core.gate.P0(index: int) qulacs_core.ClsOneQubitGate

Create projection gate to |0> subspace

qulacs_core.gate.P1(index: int) qulacs_core.ClsOneQubitGate

Create projection gate to |1> subspace

qulacs_core.gate.ParametricPauliRotation(index_list: List[int], pauli_ids: List[int], angle: float) qulacs_core.QuantumGate_SingleParameter

Create parametric multi-qubit Pauli rotation gate

qulacs_core.gate.ParametricRX(index: int, angle: float) qulacs_core.QuantumGate_SingleParameter

Create parametric Pauli-X rotation gate

qulacs_core.gate.ParametricRY(index: int, angle: float) qulacs_core.QuantumGate_SingleParameter

Create parametric Pauli-Y rotation gate

qulacs_core.gate.ParametricRZ(index: int, angle: float) qulacs_core.QuantumGate_SingleParameter

Create parametric Pauli-Z rotation gate

qulacs_core.gate.Pauli(index_list: List[int], pauli_ids: List[int]) qulacs_core.ClsPauliGate

Create multi-qubit Pauli gate

qulacs_core.gate.PauliRotation(index_list: List[int], pauli_ids: List[int], angle: float) qulacs_core.ClsPauliRotationGate

Create multi-qubit Pauli rotation

qulacs_core.gate.Probabilistic(prob_list: List[float], gate_list: List[qulacs_core.QuantumGateBase]) qulacs_core.QuantumGateBase

Create probabilistic gate

qulacs_core.gate.ProbabilisticInstrument(prob_list: List[float], gate_list: List[qulacs_core.QuantumGateBase], register: int) qulacs_core.QuantumGateBase

Create probabilistic instrument gate

qulacs_core.gate.RX(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-X rotation gate

qulacs_core.gate.RY(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-Y rotation gate

qulacs_core.gate.RZ(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-Z rotation gate

qulacs_core.gate.RandomUnitary(*args, **kwargs)

Overloaded function.

  1. RandomUnitary(index_list: List[int]) -> qulacs_core.QuantumGateMatrix

Create random unitary gate

  1. RandomUnitary(index_list: List[int], seed: int) -> qulacs_core.QuantumGateMatrix

qulacs_core.gate.ReversibleBoolean(index_list: List[int], func: Callable[[int, int], int]) qulacs_core.ClsReversibleBooleanGate

Create reversible boolean gate

qulacs_core.gate.RotInvX(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-X rotation gate

qulacs_core.gate.RotInvY(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-Y rotation gate

qulacs_core.gate.RotInvZ(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-Z rotation gate

qulacs_core.gate.RotX(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-X rotation gate

qulacs_core.gate.RotY(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-Y rotation gate

qulacs_core.gate.RotZ(index: int, angle: float) qulacs_core.ClsOneQubitRotationGate

Create Pauli-Z rotation gate

qulacs_core.gate.S(index: int) qulacs_core.ClsOneQubitGate

Create pi/4-phase gate

qulacs_core.gate.SWAP(target1: int, target2: int) qulacs_core.ClsTwoQubitGate

Create SWAP gate

qulacs_core.gate.Sdag(index: int) qulacs_core.ClsOneQubitGate

Create adjoint of pi/4-phase gate

qulacs_core.gate.SparseMatrix(index_list: List[int], matrix: scipy.sparse.csc_matrix[numpy.complex128]) qulacs_core.QuantumGateSparseMatrix

Create sparse matrix gate

qulacs_core.gate.StateReflection(state: qulacs_core.QuantumState) qulacs_core.ClsStateReflectionGate

Create state reflection gate

qulacs_core.gate.T(index: int) qulacs_core.ClsOneQubitGate

Create pi/8-phase gate

qulacs_core.gate.TOFFOLI(control1: int, control2: int, target: int) qulacs_core.QuantumGateMatrix

Create TOFFOLI gate

qulacs_core.gate.Tdag(index: int) qulacs_core.ClsOneQubitGate

Create adjoint of pi/8-phase gate

qulacs_core.gate.TwoQubitDepolarizingNoise(index1: int, index2: int, prob: float) qulacs_core.QuantumGate_Probabilistic

Create two-qubit depolarizing noise

qulacs_core.gate.U1(index: int, lambda_: float) qulacs_core.QuantumGateMatrix

Create QASM U1 gate

qulacs_core.gate.U2(index: int, phi: float, lambda_: float) qulacs_core.QuantumGateMatrix

Create QASM U2 gate

qulacs_core.gate.U3(index: int, theta: float, phi: float, lambda_: float) qulacs_core.QuantumGateMatrix

Create QASM U3 gate

qulacs_core.gate.X(index: int) qulacs_core.ClsOneQubitGate

Create Pauli-X gate

qulacs_core.gate.Y(index: int) qulacs_core.ClsOneQubitGate

Create Pauli-Y gate

qulacs_core.gate.Z(index: int) qulacs_core.ClsOneQubitGate

Create Pauli-Z gate

qulacs_core.gate.add(*args, **kwargs)

Overloaded function.

  1. add(gate1: qulacs_core.QuantumGateBase, gate2: qulacs_core.QuantumGateBase) -> qulacs_core.QuantumGateMatrix

Add quantum gate matrices

  1. add(gate_list: List[qulacs_core.QuantumGateBase]) -> qulacs_core.QuantumGateMatrix

Add quantum gate matrices

qulacs_core.gate.from_json(arg0: str) qulacs_core.QuantumGateBase

from json string

qulacs_core.gate.merge(*args, **kwargs)

Overloaded function.

  1. merge(gate1: qulacs_core.QuantumGateBase, gate2: qulacs_core.QuantumGateBase) -> qulacs_core.QuantumGateMatrix

Merge two quantum gate or gate list

  1. merge(gate_list: List[qulacs_core.QuantumGateBase]) -> qulacs_core.QuantumGateMatrix

qulacs_core.gate.sqrtX(index: int) qulacs_core.ClsOneQubitGate

Create pi/4 Pauli-X rotation gate

qulacs_core.gate.sqrtXdag(index: int) qulacs_core.ClsOneQubitGate

Create adjoint of pi/4 Pauli-X rotation gate

qulacs_core.gate.sqrtY(index: int) qulacs_core.ClsOneQubitGate

Create pi/4 Pauli-Y rotation gate

qulacs_core.gate.sqrtYdag(index: int) qulacs_core.ClsOneQubitGate

Create adjoint of pi/4 Pauli-Y rotation gate

qulacs_core.gate.to_matrix_gate(gate: qulacs_core.QuantumGateBase) qulacs_core.QuantumGateMatrix

Convert named gate to matrix gate

qulacs.observable

qulacs_core.observable.create_observable_from_openfermion_file(file_path: str) qulacs_core.Observable

Create GeneralQuantumOperator from openfermion file

qulacs_core.observable.create_observable_from_openfermion_text(text: str) qulacs_core.Observable

Create GeneralQuantumOperator from openfermion text

qulacs_core.observable.create_split_observable(arg0: str) Tuple[qulacs_core.Observable, qulacs_core.Observable]
qulacs_core.observable.from_json(json: str) qulacs_core.Observable

from json string

qulacs.quantum_operator

qulacs_core.quantum_operator.create_quantum_operator_from_openfermion_file(arg0: str) qulacs_core.GeneralQuantumOperator
qulacs_core.quantum_operator.create_quantum_operator_from_openfermion_text(arg0: str) qulacs_core.GeneralQuantumOperator
qulacs_core.quantum_operator.create_split_quantum_operator(arg0: str) Tuple[qulacs_core.GeneralQuantumOperator, qulacs_core.GeneralQuantumOperator]
qulacs_core.quantum_operator.from_json(json: str) qulacs_core.GeneralQuantumOperator

from json string

qulacs.circuit

class qulacs_core.circuit.QuantumCircuitOptimizer

Bases: pybind11_builtins.pybind11_object

merge_all(self: qulacs_core.circuit.QuantumCircuitOptimizer, circuit: qulacs_core.QuantumCircuit) qulacs_core.QuantumGateMatrix
optimize(self: qulacs_core.circuit.QuantumCircuitOptimizer, circuit: qulacs_core.QuantumCircuit, block_size: int) None

Optimize quantum circuit

optimize_light(self: qulacs_core.circuit.QuantumCircuitOptimizer, circuit: qulacs_core.QuantumCircuit) None

Optimize quantum circuit with light method

qulacs_core.circuit.from_json(arg0: str) qulacs_core.QuantumCircuit

from json string

C++ API Reference

Class Hierarchy

File Hierarchy

Full API

Namespaces
Namespace gate

Contents

Functions
Classes and Structs
Struct NoiseSimulator::Result
Nested Relationships

This struct is a nested type of Class NoiseSimulator.

Struct Documentation
struct NoiseSimulator::Result

Public Functions

Result(const std::vector<std::pair<QuantumState*, UINT>> &result_)
~Result()
std::vector<ITYPE> sampling() const

Public Members

std::vector<std::pair<QuantumState*, UINT>> result
Struct NoiseSimulator::SamplingRequest
Nested Relationships

This struct is a nested type of Class NoiseSimulator.

Struct Documentation
struct NoiseSimulator::SamplingRequest

Public Functions

inline SamplingRequest(std::vector<UINT> init_gate_pos, UINT init_num_of_sampling)

Public Members

std::vector<UINT> gate_pos
UINT num_of_sampling
Class AdamOptimizer
Inheritance Relationships
Base Type
Class Documentation
class AdamOptimizer : public GradientBasedOptimizer

Public Functions

inline AdamOptimizer(UINT trainable_parameter_count, double learning_rate = 0.001, double beta1 = 0.9, double beta2 = 0.999, double epsilon = 1e-8)
inline virtual ~AdamOptimizer()
inline virtual void apply_gradient(std::vector<double> *parameter, const std::vector<double> &gradient) override
Class BooleanFormula
Class Documentation
class BooleanFormula

Public Functions

inline virtual double evaluate(std::vector<UINT> binary_string)
inline virtual UINT get_variable_count() const
Class BooleanOptimizationProblem
Class Documentation
class BooleanOptimizationProblem

Public Functions

inline BooleanOptimizationProblem(BooleanFormula *boolean_formula)
inline virtual double compute_loss(const std::vector<UINT> &binary_string) const
inline virtual double compute_loss(const std::vector<double> answer_distribution) const
Class CausalConeSimulator
Class Documentation
class CausalConeSimulator

Public Functions

inline CausalConeSimulator(const ParametricQuantumCircuit &_init_circuit, const Observable &_init_observable)
inline ~CausalConeSimulator()
inline void build()
inline CPPCTYPE get_expectation_value()
inline std::vector<std::vector<ParametricQuantumCircuit*>> get_circuit_list()
inline std::vector<std::vector<PauliOperator>> get_pauli_operator_list()
inline std::vector<CPPCTYPE> get_coef_list()

Public Members

ParametricQuantumCircuit *init_circuit
Observable *init_observable
std::vector<std::vector<ParametricQuantumCircuit*>> circuit_list
std::vector<std::vector<PauliOperator>> pauli_operator_list
std::vector<CPPCTYPE> coef_list
bool build_run = false
Class ClassificationProblem
Class Documentation
class ClassificationProblem

Public Functions

inline ClassificationProblem(std::vector<std::vector<double>> input_data, std::vector<UINT> label_data)
inline virtual UINT get_input_dim() const
inline virtual std::vector<double> get_input_data(UINT sample_id) const
inline virtual UINT get_category_count() const
inline virtual UINT get_output_data(UINT sample_id) const
inline virtual double compute_loss(UINT sample_id, std::vector<double> probability_distribution) const
Class ClsNoisyEvolution
Inheritance Relationships
Base Type
Class Documentation
class ClsNoisyEvolution : public QuantumGateBase

Public Functions

ClsNoisyEvolution(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time, double dt = 1e-6)
~ClsNoisyEvolution()
inline virtual void set_matrix(ComplexMatrix&) const override
inline virtual void set_seed(int seed) override
inline virtual ClsNoisyEvolution *copy() const override
inline virtual GeneralQuantumOperator *get_effective_hamiltonian() const
inline virtual void set_find_collapse_max_steps(int n)
virtual void update_quantum_state(QuantumStateBase *state) override
virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

Class ClsNoisyEvolution_auto
Inheritance Relationships
Base Type
Class Documentation
class ClsNoisyEvolution_auto : public QuantumGateBase

Public Functions

inline ClsNoisyEvolution_auto()
inline ClsNoisyEvolution_auto(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time)
inline ~ClsNoisyEvolution_auto()
inline virtual void set_matrix(ComplexMatrix&) const override
inline virtual void set_seed(int seed) override
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGateBase *copy() const override
Class ClsNoisyEvolution_fast
Inheritance Relationships
Base Type
Class Documentation
class ClsNoisyEvolution_fast : public QuantumGateBase

Public Functions

ClsNoisyEvolution_fast(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time)
inline ~ClsNoisyEvolution_fast()
inline virtual void set_matrix(ComplexMatrix&) const override
inline virtual void set_seed(int seed) override
inline virtual ClsNoisyEvolution_fast *copy() const override
inline virtual GeneralQuantumOperator *get_effective_hamiltonian() const
inline virtual void set_find_collapse_max_steps(int n)
inline virtual void change_time(double time)
virtual void update_quantum_state(QuantumStateBase *state) override
virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

Class ClsOneControlOneTargetGate
Inheritance Relationships
Base Type
Class Documentation
class ClsOneControlOneTargetGate : public QuantumGateBase

Public Functions

inline explicit ClsOneControlOneTargetGate()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsOneControlOneTargetGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline void CNOTGateinit(UINT control_qubit_index, UINT target_qubit_index)
inline void CZGateinit(UINT control_qubit_index, UINT target_qubit_index)
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual ClsOneControlOneTargetGate *get_inverse(void) const override

Protected Types

using UpdateFunc = void (*)(UINT, UINT, CTYPE*, ITYPE)
using UpdateFuncGpu = void (*)(UINT, UINT, void*, ITYPE, void*, UINT)

Protected Attributes

UpdateFunc _update_func
UpdateFunc _update_func_dm
UpdateFuncGpu _update_func_gpu
ComplexMatrix _matrix_element
Class ClsOneQubitGate
Inheritance Relationships
Base Type
Class Documentation
class ClsOneQubitGate : public QuantumGateBase

Public Functions

inline explicit ClsOneQubitGate()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsOneQubitGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline void IGateinit(UINT target_qubit_index)
inline void XGateinit(UINT target_qubit_index)
inline void YGateinit(UINT target_qubit_index)
inline void ZGateinit(UINT target_qubit_index)
inline void HGateinit(UINT target_qubit_index)
inline void SGateinit(UINT target_qubit_index)
inline void SdagGateinit(UINT target_qubit_index)
inline void TGateinit(UINT target_qubit_index)
inline void TdagGateinit(UINT target_qubit_index)
inline void sqrtXGateinit(UINT target_qubit_index)
inline void sqrtXdagGateinit(UINT target_qubit_index)
inline void sqrtYGateinit(UINT target_qubit_index)
inline void sqrtYdagGateinit(UINT target_qubit_index)
inline void P0Gateinit(UINT target_qubit_index)
inline void P1Gateinit(UINT target_qubit_index)
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

virtual ClsOneQubitGate *get_inverse(void) const override

Protected Types

using UpdateFunc = void (*)(UINT, CTYPE*, ITYPE)
using UpdateFuncGpu = void (*)(UINT, void*, ITYPE, void*, UINT)

Protected Attributes

UpdateFunc _update_func
UpdateFunc _update_func_dm
UpdateFuncGpu _update_func_gpu
ComplexMatrix _matrix_element
Class ClsOneQubitRotationGate
Inheritance Relationships
Base Type
Class Documentation
class ClsOneQubitRotationGate : public QuantumGateBase

Public Functions

inline explicit ClsOneQubitRotationGate()
inline explicit ClsOneQubitRotationGate(double angle)
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsOneQubitRotationGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline void RXGateinit(UINT target_qubit_index, double angle)
inline void RYGateinit(UINT target_qubit_index, double angle)
inline void RZGateinit(UINT target_qubit_index, double angle)
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

virtual ClsOneQubitRotationGate *get_inverse(void) const override

Protected Types

using UpdateFunc = void (*)(UINT, double, CTYPE*, ITYPE)
using UpdateFuncGpu = void (*)(UINT, double, void*, ITYPE, void*, UINT)

Protected Attributes

UpdateFunc _update_func
UpdateFunc _update_func_dm
UpdateFuncGpu _update_func_gpu
ComplexMatrix _matrix_element
double _angle
Class ClsParametricPauliRotationGate
Inheritance Relationships
Base Type
Class Documentation
class ClsParametricPauliRotationGate : public QuantumGate_SingleParameter

Public Functions

inline ClsParametricPauliRotationGate(double angle, PauliOperator *pauli)
inline virtual ~ClsParametricPauliRotationGate()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsParametricPauliRotationGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual PauliOperator *get_pauli() const
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual ClsParametricPauliRotationGate *get_inverse() const override

Protected Attributes

PauliOperator *_pauli
Class ClsParametricRXGate
Inheritance Relationships
Base Type
Class Documentation
class ClsParametricRXGate : public QuantumGate_SingleParameterOneQubitRotation

Public Functions

inline ClsParametricRXGate(UINT target_qubit_index, double angle)
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual ClsParametricRXGate *copy() const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual ClsParametricRXGate *get_inverse() const override
Class ClsParametricRYGate
Inheritance Relationships
Base Type
Class Documentation
class ClsParametricRYGate : public QuantumGate_SingleParameterOneQubitRotation

Public Functions

inline ClsParametricRYGate(UINT target_qubit_index, double angle)
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual ClsParametricRYGate *copy() const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual ClsParametricRYGate *get_inverse() const override
Class ClsParametricRZGate
Inheritance Relationships
Base Type
Class Documentation
class ClsParametricRZGate : public QuantumGate_SingleParameterOneQubitRotation

Public Functions

inline ClsParametricRZGate(UINT target_qubit_index, double angle)
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual ClsParametricRZGate *copy() const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual ClsParametricRZGate *get_inverse() const override
Class ClsPauliGate
Inheritance Relationships
Base Type
Class Documentation
class ClsPauliGate : public QuantumGateBase

Public Functions

inline explicit ClsPauliGate(PauliOperator *pauli)
inline virtual ~ClsPauliGate()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsPauliGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

Protected Attributes

PauliOperator *_pauli
Class ClsPauliRotationGate
Inheritance Relationships
Base Type
Class Documentation
class ClsPauliRotationGate : public QuantumGateBase

Public Functions

inline ClsPauliRotationGate(double angle, PauliOperator *pauli)
inline virtual ~ClsPauliRotationGate()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsPauliRotationGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual ClsPauliRotationGate *get_inverse(void) const override

Protected Attributes

double _angle
PauliOperator *_pauli
Class ClsReversibleBooleanGate
Inheritance Relationships
Base Type
Class Documentation
class ClsReversibleBooleanGate : public QuantumGateBase

Public Functions

inline ClsReversibleBooleanGate(std::vector<UINT> target_qubit_index_list, std::function<ITYPE(ITYPE, ITYPE)> _function_ptr)
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsReversibleBooleanGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
Class ClsStateReflectionGate
Inheritance Relationships
Base Type
Class Documentation
class ClsStateReflectionGate : public QuantumGateBase

Public Functions

inline explicit ClsStateReflectionGate(const QuantumState *_reflection_state)
inline virtual ~ClsStateReflectionGate()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsStateReflectionGate *copy() const override
inline virtual void set_matrix(ComplexMatrix&) const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

Class ClsTwoQubitGate
Inheritance Relationships
Base Type
Class Documentation
class ClsTwoQubitGate : public QuantumGateBase

Public Functions

inline explicit ClsTwoQubitGate()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual ClsTwoQubitGate *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline void SWAPGateinit(UINT target_qubit_index1, UINT target_qubit_index2)
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual ClsTwoQubitGate *get_inverse(void) const override

Protected Types

using UpdateFunc = void (*)(UINT, UINT, CTYPE*, ITYPE)
using UpdateFuncGpu = void (*)(UINT, UINT, void*, ITYPE, void*, UINT)

Protected Attributes

UpdateFunc _update_func
UpdateFunc _update_func_dm
UpdateFuncGpu _update_func_gpu
ComplexMatrix _matrix_element
Class ControlQubitInfo
Inheritance Relationships
Base Type
Class Documentation
class ControlQubitInfo : public QubitInfo

Public Functions

inline UINT control_value() const
inline ControlQubitInfo(void)
inline explicit ControlQubitInfo(UINT index_)
inline ControlQubitInfo(UINT index_, UINT control_value_)
virtual bool is_commute_with(const TargetQubitInfo &info) const
virtual bool is_commute_with(const ControlQubitInfo &info) const
Class DensityMatrixCpu
Inheritance Relationships
Base Type
Class Documentation
class DensityMatrixCpu : public QuantumStateBase

Public Functions

inline explicit DensityMatrixCpu(UINT qubit_count_)
inline virtual ~DensityMatrixCpu()
inline virtual void set_zero_state() override
inline virtual void set_zero_norm_state() override
inline virtual void set_computational_basis(ITYPE comp_basis) override
inline virtual void set_Haar_random_state() override
inline virtual void set_Haar_random_state(UINT seed) override
inline virtual double get_zero_probability(UINT target_qubit_index) const override
inline virtual double get_marginal_probability(std::vector<UINT> measured_values) const override
inline virtual double get_entropy() const override
inline virtual double get_squared_norm() const override
inline virtual double get_squared_norm_single_thread() const override
inline virtual void normalize(double squared_norm) override
inline virtual void normalize_single_thread(double squared_norm) override
inline virtual DensityMatrixCpu *allocate_buffer() const override
inline virtual DensityMatrixCpu *copy() const override
inline virtual void load(const QuantumStateBase *_state) override
inline virtual void load(const std::vector<CPPCTYPE> &_state) override
inline virtual void load(const Eigen::VectorXcd &_state)
inline virtual void load(const ComplexMatrix &_state)
inline virtual void load(const CPPCTYPE *_state) override
inline virtual const std::string get_device_name() const override
inline virtual void *data() const override
inline virtual CPPCTYPE *data_cpp() const override
inline virtual CTYPE *data_c() const override
inline virtual CTYPE *duplicate_data_c() const override
inline virtual CPPCTYPE *duplicate_data_cpp() const override
inline virtual void add_state(const QuantumStateBase *state) override
inline virtual void add_state_with_coef(CPPCTYPE coef, const QuantumStateBase *state) override
inline virtual void add_state_with_coef_single_thread(CPPCTYPE coef, const QuantumStateBase *state) override
inline virtual void multiply_coef(CPPCTYPE coef) override
inline virtual void multiply_elementwise_function(const std::function<CPPCTYPE(ITYPE)>&) override
inline virtual std::vector<ITYPE> sampling(UINT sampling_count) override
inline virtual std::vector<ITYPE> sampling(UINT sampling_count, UINT random_seed) override
inline virtual std::string to_string() const override
inline virtual boost::property_tree::ptree to_ptree() const override
Class DiagonalizationEnergyMinimizationSolver
Class Documentation
class DiagonalizationEnergyMinimizationSolver

Public Functions

inline DiagonalizationEnergyMinimizationSolver()
inline virtual ~DiagonalizationEnergyMinimizationSolver()
inline virtual void solve(EnergyMinimizationProblem *instance)
inline virtual double get_loss()

Public Members

bool verbose
Class DuplicatedQubitIndexException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class DuplicatedQubitIndexException : public logic_error

Public Functions

inline DuplicatedQubitIndexException(const std::string &message)
Class EnergyMinimizationProblem
Class Documentation
class EnergyMinimizationProblem

Public Functions

inline EnergyMinimizationProblem(Observable *observable)
inline virtual ~EnergyMinimizationProblem()
inline virtual UINT get_term_count() const
inline virtual const PauliOperator *get_Pauli_operator(UINT index) const
inline virtual ITYPE get_state_dim() const
inline virtual UINT get_qubit_count() const
inline virtual double compute_loss(const QuantumStateBase *state) const
Class GateIndexOutOfRangeException
Inheritance Relationships
Base Type
  • public out_of_range

Class Documentation
class GateIndexOutOfRangeException : public out_of_range

Public Functions

inline GateIndexOutOfRangeException(const std::string &message)
Class GeneralQuantumOperator
Inheritance Relationships
Derived Type
Class Documentation
class GeneralQuantumOperator

Subclassed by HermitianQuantumOperator

Public Functions

explicit GeneralQuantumOperator(const UINT qubit_count)
GeneralQuantumOperator(const GeneralQuantumOperator &obj)
virtual ~GeneralQuantumOperator()
inline virtual bool is_hermitian() const
virtual void add_operator(const PauliOperator *mpt)
virtual void add_operator_move(PauliOperator *mpt)
virtual void add_operator_copy(const PauliOperator *mpt)
virtual void add_operator(const CPPCTYPE coef, std::string pauli_string)
virtual void add_operator(const std::vector<UINT> &target_qubit_index_list, const std::vector<UINT> &target_qubit_pauli_list, CPPCTYPE coef)
inline virtual UINT get_qubit_count() const
inline virtual ITYPE get_state_dim() const
inline virtual UINT get_term_count() const
inline virtual const PauliOperator *get_term(UINT index) const
inline virtual std::vector<PauliOperator*> get_terms() const
virtual GeneralQuantumOperator *get_dagger() const
virtual std::string to_string() const
virtual CPPCTYPE get_expectation_value(const QuantumStateBase *state) const
virtual CPPCTYPE get_expectation_value_single_thread(const QuantumStateBase *state) const
virtual CPPCTYPE get_transition_amplitude(const QuantumStateBase *state_bra, const QuantumStateBase *state_ket) const
void add_random_operator(const UINT operator_count)
void add_random_operator(const UINT operator_count, UINT seed)
virtual CPPCTYPE solve_ground_state_eigenvalue_by_arnoldi_method(QuantumStateBase *state, const UINT iter_count, const CPPCTYPE mu = 0.0) const
virtual CPPCTYPE solve_ground_state_eigenvalue_by_power_method(QuantumStateBase *state, const UINT iter_count, const CPPCTYPE mu = 0.0) const
void apply_to_state(QuantumStateBase *work_state, const QuantumStateBase &state_to_be_multiplied, QuantumStateBase *dst_state) const
void apply_to_state(QuantumStateBase *state, QuantumStateBase *dst_state) const
void apply_to_state_single_thread(QuantumStateBase *state, QuantumStateBase *dst_state) const
virtual GeneralQuantumOperator *copy() const
virtual boost::property_tree::ptree to_ptree() const
GeneralQuantumOperator operator+(const GeneralQuantumOperator &target) const
GeneralQuantumOperator operator+(const PauliOperator &target) const
GeneralQuantumOperator &operator+=(const GeneralQuantumOperator &target)
GeneralQuantumOperator &operator+=(const PauliOperator &target)
GeneralQuantumOperator operator-(const GeneralQuantumOperator &target) const
GeneralQuantumOperator operator-(const PauliOperator &target) const
GeneralQuantumOperator &operator-=(const GeneralQuantumOperator &target)
GeneralQuantumOperator &operator-=(const PauliOperator &target)
GeneralQuantumOperator operator*(const GeneralQuantumOperator &target) const
GeneralQuantumOperator operator*(const PauliOperator &target) const
GeneralQuantumOperator operator*(CPPCTYPE target) const
GeneralQuantumOperator &operator*=(const GeneralQuantumOperator &target)
GeneralQuantumOperator &operator*=(const PauliOperator &target)
GeneralQuantumOperator &operator*=(CPPCTYPE target)

Protected Functions

void _apply_pauli_to_state(std::vector<UINT> pauli_id_list, std::vector<UINT> target_index_list, QuantumStateBase *state) const
void _apply_pauli_to_state_single_thread(std::vector<UINT> pauli_id_list, std::vector<UINT> target_index_list, QuantumStateBase *state) const
CPPCTYPE calculate_default_mu() const
Class GradCalculator
Class Documentation
class GradCalculator

Public Functions

std::vector<std::complex<double>> calculate_grad(ParametricQuantumCircuit &x, Observable &obs, std::vector<double> theta)
std::vector<std::complex<double>> calculate_grad(ParametricQuantumCircuit &x, Observable &obs)
Class GradientBasedOptimizer
Inheritance Relationships
Base Type
Derived Types
Class Documentation
class GradientBasedOptimizer : public Optimizer

Subclassed by AdamOptimizer, GradientDecentOptimizer

Public Functions

inline GradientBasedOptimizer(UINT trainable_parameter_count)
inline virtual ~GradientBasedOptimizer()
virtual void apply_gradient(std::vector<double> *parameter, const std::vector<double> &gradient) = 0
Class GradientByHalfPi
Inheritance Relationships
Base Type
Class Documentation
class GradientByHalfPi : public QuantumCircuitGradientDifferentiation

Public Functions

virtual double compute_gradient(ParametricQuantumCircuitSimulator *sim, const EnergyMinimizationProblem *instance, const std::vector<double> &parameter, std::vector<double> *gradient) override
Class GradientDecentOptimizer
Inheritance Relationships
Base Type
Class Documentation
class GradientDecentOptimizer : public GradientBasedOptimizer

Public Functions

inline GradientDecentOptimizer(UINT trainable_parameter_count, double learning_rate = 0.01)
inline virtual ~GradientDecentOptimizer()
inline virtual void apply_gradient(std::vector<double> *parameter, const std::vector<double> &gradient) override
Class GradientFreeOptimizer
Inheritance Relationships
Base Type
Class Documentation
class GradientFreeOptimizer : public Optimizer

Public Functions

inline GradientFreeOptimizer(UINT trainable_parameter_count)
inline virtual ~GradientFreeOptimizer()
virtual void update_parameter(std::vector<double> *next_parameter, double previous_loss) = 0
Class HermitianQuantumOperator
Inheritance Relationships
Base Type
Class Documentation
class HermitianQuantumOperator : public GeneralQuantumOperator

Public Functions

virtual void add_operator(const PauliOperator *mpt) override
virtual void add_operator_move(PauliOperator *mpt) override
virtual void add_operator_copy(const PauliOperator *mpt) override
virtual void add_operator(CPPCTYPE coef, std::string pauli_string) override
virtual CPPCTYPE get_expectation_value(const QuantumStateBase *state) const override
CPPCTYPE solve_ground_state_eigenvalue_by_lanczos_method(QuantumStateBase *init_state, const UINT iter_count, const CPPCTYPE mu = 0.0) const
inline virtual HermitianQuantumOperator *copy() const override
virtual std::string to_string() const override
Class InvalidControlQubitException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidControlQubitException : public logic_error

Public Functions

inline InvalidControlQubitException(const std::string &message)
Class InvalidMatrixGateSizeException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidMatrixGateSizeException : public logic_error

Public Functions

inline InvalidMatrixGateSizeException(const std::string &message)
Class InvalidNoiseTypeIdentifierException
Inheritance Relationships
Base Type
  • public domain_error

Class Documentation
class InvalidNoiseTypeIdentifierException : public domain_error

Public Functions

inline InvalidNoiseTypeIdentifierException(const std::string &message)
Class InvalidObservableException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidObservableException : public logic_error

Public Functions

inline InvalidObservableException(const std::string &message)
Class InvalidOpenfermionFormatException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidOpenfermionFormatException : public logic_error

Public Functions

inline InvalidOpenfermionFormatException(const std::string &message)
Class InvalidPauliIdentifierException
Inheritance Relationships
Base Type
  • public domain_error

Class Documentation
class InvalidPauliIdentifierException : public domain_error

Public Functions

inline InvalidPauliIdentifierException(const std::string &message)
Class InvalidProbabilityDistributionException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidProbabilityDistributionException : public logic_error

Public Functions

inline InvalidProbabilityDistributionException(const std::string &message)
Class InvalidQuantumOperatorException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidQuantumOperatorException : public logic_error

Public Functions

inline InvalidQuantumOperatorException(const std::string &message)
Class InvalidQubitCountException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidQubitCountException : public logic_error

Public Functions

inline InvalidQubitCountException(const std::string &message)
Class InvalidStateVectorSizeException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class InvalidStateVectorSizeException : public logic_error

Public Functions

inline InvalidStateVectorSizeException(const std::string &message)
Class IOException
Inheritance Relationships
Base Type
  • public runtime_error

Class Documentation
class IOException : public runtime_error

Public Functions

inline IOException(const std::string &message)
Class KAK_data
Class Documentation
class KAK_data

Public Members

QuantumGateMatrix *single_qubit_operations_before[2]
double interaction_coefficients[3]
QuantumGateMatrix *single_qubit_operations_after[2]
Class MatrixIndexOutOfRangeException
Inheritance Relationships
Base Type
  • public out_of_range

Class Documentation
class MatrixIndexOutOfRangeException : public out_of_range

Public Functions

inline MatrixIndexOutOfRangeException(const std::string &message)
Class NoiseSimulator
Nested Relationships
Nested Types
Class Documentation
class NoiseSimulator

Public Functions

explicit NoiseSimulator(const QuantumCircuit *init_circuit, const QuantumState *init_state = NULL)
virtual ~NoiseSimulator()
virtual std::vector<ITYPE> execute(const UINT sample_count)
virtual Result *execute_and_get_result(const UINT execution_count)
struct Result

Public Functions

Result(const std::vector<std::pair<QuantumState*, UINT>> &result_)
~Result()
std::vector<ITYPE> sampling() const

Public Members

std::vector<std::pair<QuantumState*, UINT>> result
Class NonHermitianException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class NonHermitianException : public logic_error

Public Functions

inline NonHermitianException(const std::string &message)
Class NotImplementedException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class NotImplementedException : public logic_error

Public Functions

inline NotImplementedException(const std::string &message)
Class OperatorIndexOutOfRangeException
Inheritance Relationships
Base Type
  • public out_of_range

Class Documentation
class OperatorIndexOutOfRangeException : public out_of_range

Public Functions

inline OperatorIndexOutOfRangeException(const std::string &message)
Class Optimizer
Inheritance Relationships
Derived Types
Class Documentation
class Optimizer

Subclassed by GradientBasedOptimizer, GradientFreeOptimizer

Protected Functions

inline Optimizer(UINT trainable_parameter_count)
inline virtual ~Optimizer()

Protected Attributes

UINT _trainable_parameter_count
Class ParameterIndexOutOfRangeException
Inheritance Relationships
Base Type
  • public out_of_range

Class Documentation
class ParameterIndexOutOfRangeException : public out_of_range

Public Functions

inline ParameterIndexOutOfRangeException(const std::string &message)
Class ParametricCircuitBuilder
Inheritance Relationships
Base Type
Class Documentation
class ParametricCircuitBuilder : public QuantumCircuitBuilder
Class ParametricQuantumCircuit
Inheritance Relationships
Base Type
Class Documentation
class ParametricQuantumCircuit : public QuantumCircuit

Public Functions

ParametricQuantumCircuit(UINT qubit_count)
ParametricQuantumCircuit *copy() const
virtual void add_parametric_gate(QuantumGate_SingleParameter *gate)
virtual void add_parametric_gate(QuantumGate_SingleParameter *gate, UINT index)
virtual void add_parametric_gate_copy(QuantumGate_SingleParameter *gate)
virtual void add_parametric_gate_copy(QuantumGate_SingleParameter *gate, UINT index)
virtual UINT get_parameter_count() const
virtual double get_parameter(UINT index) const
virtual void set_parameter(UINT index, double value)
virtual UINT get_parametric_gate_position(UINT index) const
virtual void add_gate(QuantumGateBase *gate) override
virtual void add_gate(QuantumGateBase *gate, UINT index) override
virtual void add_gate_copy(const QuantumGateBase *gate) override
virtual void add_gate_copy(const QuantumGateBase *gate, UINT index) override
virtual void remove_gate(UINT index) override
virtual void merge_circuit(const ParametricQuantumCircuit *circuit)
virtual std::string to_string() const override
virtual void add_parametric_RX_gate(UINT target_index, double initial_angle)
virtual void add_parametric_RY_gate(UINT target_index, double initial_angle)
virtual void add_parametric_RZ_gate(UINT target_index, double initial_angle)
virtual void add_parametric_multi_Pauli_rotation_gate(std::vector<UINT> target, std::vector<UINT> pauli_id, double initial_angle)
virtual std::vector<double> backprop(GeneralQuantumOperator *obs)
virtual std::vector<double> backprop_inner_product(QuantumState *bistate)
virtual boost::property_tree::ptree to_ptree() const override

Friends

friend std::ostream &operator<<(std::ostream &os, const ParametricQuantumCircuit&)
friend std::ostream &operator<<(std::ostream &os, const ParametricQuantumCircuit *circuit)
Class ParametricQuantumCircuitSimulator
Inheritance Relationships
Base Type
Class Documentation
class ParametricQuantumCircuitSimulator : public QuantumCircuitSimulator

Public Functions

ParametricQuantumCircuitSimulator(ParametricQuantumCircuit *circuit, QuantumStateBase *state = NULL)
double get_parameter(UINT index) const
void add_parameter_value(UINT index, double value)
void set_parameter_value(UINT index, double value)
UINT get_parametric_gate_count()
UINT get_parametric_gate_position(UINT index)
Class PauliOperator
Class Documentation
class PauliOperator

Public Functions

inline std::vector<UINT> get_index_list() const
inline UINT get_qubit_count() const
inline std::vector<UINT> get_pauli_id_list() const
inline explicit PauliOperator(CPPCTYPE coef = 1.)
explicit PauliOperator(std::string strings, CPPCTYPE coef = 1.)
PauliOperator(const std::vector<UINT> &target_qubit_index_list, std::string Pauli_operator_type_list, CPPCTYPE coef = 1.)
explicit PauliOperator(const std::vector<UINT> &pauli_list, CPPCTYPE coef = 1.)
PauliOperator(const std::vector<UINT> &target_qubit_index_list, const std::vector<UINT> &target_qubit_pauli_list, CPPCTYPE coef = 1.)
PauliOperator(const boost::dynamic_bitset<> &x, const boost::dynamic_bitset<> &z, CPPCTYPE coef = 1.)
inline virtual CPPCTYPE get_coef() const
inline virtual boost::dynamic_bitset get_x_bits() const
inline virtual boost::dynamic_bitset get_z_bits() const
inline virtual ~PauliOperator()
virtual void add_single_Pauli(UINT qubit_index, UINT pauli_type)
virtual CPPCTYPE get_expectation_value(const QuantumStateBase *state) const
virtual CPPCTYPE get_expectation_value_single_thread(const QuantumStateBase *state) const
virtual CPPCTYPE get_transition_amplitude(const QuantumStateBase *state_bra, const QuantumStateBase *state_ket) const
virtual PauliOperator *copy() const
virtual void change_coef(CPPCTYPE new_coef)
virtual std::string get_pauli_string() const
virtual boost::property_tree::ptree to_ptree() const
PauliOperator operator*(const PauliOperator &target) const
PauliOperator operator*(CPPCTYPE target) const
PauliOperator &operator*=(const PauliOperator &target)
PauliOperator &operator*=(CPPCTYPE target)
Class QuantumCircuit
Inheritance Relationships
Derived Type
Class Documentation
class QuantumCircuit

Subclassed by ParametricQuantumCircuit

Public Functions

explicit QuantumCircuit(UINT qubit_count)
QuantumCircuit *copy() const
virtual ~QuantumCircuit()
virtual void add_gate(QuantumGateBase *gate)
virtual void add_gate(QuantumGateBase *gate, UINT index)
virtual void add_gate_copy(const QuantumGateBase *gate)
virtual void add_gate_copy(const QuantumGateBase *gate, UINT index)
virtual void add_noise_gate(QuantumGateBase *gate, std::string noise_type, double noise_prob)
void add_noise_gate_copy(QuantumGateBase *gate, std::string noise_type, double noise_prob)
virtual void remove_gate(UINT index)
inline void merge_circuit(const QuantumCircuit *circuit)
void update_quantum_state(QuantumStateBase *state)
void update_quantum_state(QuantumStateBase *state, UINT start_index, UINT end_index)
bool is_Clifford() const
bool is_Gaussian() const
UINT calculate_depth() const
virtual std::string to_string() const
virtual void add_X_gate(UINT target_index)
virtual void add_Y_gate(UINT target_index)
virtual void add_Z_gate(UINT target_index)
virtual void add_H_gate(UINT target_index)
virtual void add_S_gate(UINT target_index)
virtual void add_Sdag_gate(UINT target_index)
virtual void add_T_gate(UINT target_index)
virtual void add_Tdag_gate(UINT target_index)
virtual void add_sqrtX_gate(UINT target_index)
virtual void add_sqrtXdag_gate(UINT target_index)
virtual void add_sqrtY_gate(UINT target_index)
virtual void add_sqrtYdag_gate(UINT target_index)
virtual void add_P0_gate(UINT target_index)
virtual void add_P1_gate(UINT target_index)
virtual void add_CNOT_gate(UINT control_index, UINT target_index)
virtual void add_CZ_gate(UINT control_index, UINT target_index)
virtual void add_SWAP_gate(UINT target_index1, UINT target_index2)
virtual void add_RX_gate(UINT target_index, double angle)
virtual void add_RY_gate(UINT target_index, double angle)
virtual void add_RZ_gate(UINT target_index, double angle)
virtual void add_RotInvX_gate(UINT target_index, double angle)
virtual void add_RotInvY_gate(UINT target_index, double angle)
virtual void add_RotInvZ_gate(UINT target_index, double angle)
virtual void add_RotX_gate(UINT target_index, double angle)
virtual void add_RotY_gate(UINT target_index, double angle)
virtual void add_RotZ_gate(UINT target_index, double angle)
virtual void add_U1_gate(UINT target_index, double phi)
virtual void add_U2_gate(UINT target_index, double phi, double psi)
virtual void add_U3_gate(UINT target_index, double phi, double psi, double lambda)
virtual void add_multi_Pauli_gate(std::vector<UINT> target_index_list, std::vector<UINT> pauli_id_list)
virtual void add_multi_Pauli_gate(const PauliOperator &pauli_operator)
virtual void add_multi_Pauli_rotation_gate(std::vector<UINT> target_index_list, std::vector<UINT> pauli_id_list, double angle)
virtual void add_multi_Pauli_rotation_gate(const PauliOperator &pauli_operator)
virtual void add_diagonal_observable_rotation_gate(const Observable &observable, double angle)
virtual void add_observable_rotation_gate(const Observable &observable, double angle, UINT num_repeats = 0)
virtual void add_dense_matrix_gate(UINT target_index, const ComplexMatrix &matrix)
virtual void add_dense_matrix_gate(std::vector<UINT> target_index_list, const ComplexMatrix &matrix)
virtual void add_random_unitary_gate(std::vector<UINT> target_index_list)
virtual void add_random_unitary_gate(std::vector<UINT> target_index_list, UINT seed)
virtual boost::property_tree::ptree to_ptree() const
virtual QuantumCircuit *get_inverse(void)

Public Members

const UINT &qubit_count
const std::vector<QuantumGateBase*> &gate_list

Protected Functions

QuantumCircuit(const QuantumCircuit &obj)
QuantumCircuit &operator=(const QuantumCircuit&) = delete

Protected Attributes

std::vector<QuantumGateBase*> _gate_list
UINT _qubit_count

Friends

friend std::ostream &operator<<(std::ostream &os, const QuantumCircuit&)
friend std::ostream &operator<<(std::ostream &os, const QuantumCircuit *gate)
Class QuantumCircuitBuilder
Inheritance Relationships
Derived Type
Class Documentation
class QuantumCircuitBuilder

Subclassed by ParametricCircuitBuilder

Public Functions

virtual QuantumCircuit *create_circuit(UINT qubit_count) const = 0
Class QuantumCircuitEnergyMinimizationSolver
Class Documentation
class QuantumCircuitEnergyMinimizationSolver

Public Functions

inline QuantumCircuitEnergyMinimizationSolver(const std::function<ParametricQuantumCircuit*(UINT, UINT)> *circuit_generator, UINT param_count = 0)
inline virtual ~QuantumCircuitEnergyMinimizationSolver()
inline virtual void solve(EnergyMinimizationProblem *instance, UINT max_iteration = 100, std::string optimizer_name = "GD", std::string differentiation_method = "HalfPi")
inline virtual double get_loss()
inline virtual std::vector<double> get_parameter()
inline ParametricQuantumCircuitSimulator *get_quantum_circuit_simulator()

Public Members

bool verbose
Class QuantumCircuitGradientDifferentiation
Inheritance Relationships
Derived Type
Class Documentation
class QuantumCircuitGradientDifferentiation

Subclassed by GradientByHalfPi

Public Functions

virtual double compute_gradient(ParametricQuantumCircuitSimulator *sim, const EnergyMinimizationProblem *instance, const std::vector<double> &parameter, std::vector<double> *gradient) = 0
Class QuantumCircuitOptimizer
Class Documentation
class QuantumCircuitOptimizer

Public Functions

inline QuantumCircuitOptimizer()
inline virtual ~QuantumCircuitOptimizer()
void optimize(QuantumCircuit *circuit, UINT max_block_size = 2)
void optimize_light(QuantumCircuit *circuit)
QuantumGateMatrix *merge_all(const QuantumCircuit *circuit)
Class QuantumCircuitSimulator
Inheritance Relationships
Derived Type
Class Documentation
class QuantumCircuitSimulator

Subclassed by ParametricQuantumCircuitSimulator

Public Functions

explicit QuantumCircuitSimulator(QuantumCircuit *circuit, QuantumStateBase *initial_state = NULL)
~QuantumCircuitSimulator()
void initialize_state(ITYPE computationl_basis = 0)
void initialize_random_state()
void initialize_random_state(UINT seed)
void simulate()
void simulate_range(UINT start, UINT end)
CPPCTYPE get_expectation_value(const Observable *observable)
UINT get_gate_count()
void copy_state_to_buffer()
void copy_state_from_buffer()
void swap_state_and_buffer()
inline const QuantumStateBase *get_state_ptr() const
Class QuantumGate_Adaptive
Inheritance Relationships
Base Type
Class Documentation
class QuantumGate_Adaptive : public QuantumGateBase

Public Functions

inline explicit QuantumGate_Adaptive(QuantumGateBase *gate, std::function<bool(const std::vector<UINT>&)> func_without_id)
inline explicit QuantumGate_Adaptive(QuantumGateBase *gate, std::function<bool(const std::vector<UINT>&, UINT)> func_with_id, UINT id)
inline virtual ~QuantumGate_Adaptive()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGate_Adaptive *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override

Protected Attributes

QuantumGateBase *_gate
std::function<bool(const std::vector<UINT>&)> _func_without_id
std::function<bool(const std::vector<UINT>&, UINT)> _func_with_id
const int _id
Class QuantumGate_CP
Inheritance Relationships
Base Type
Class Documentation
class QuantumGate_CP : public QuantumGateBase

Public Functions

inline explicit QuantumGate_CP(std::vector<QuantumGateBase*> gate_list, bool state_normalize, bool probability_normalize, bool assign_zero_if_not_matched)
inline virtual ~QuantumGate_CP()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGate_CP *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual std::vector<QuantumGateBase*> get_gate_list()

Protected Attributes

Random random
std::vector<QuantumGateBase*> _gate_list
const bool _state_normalize
const bool _probability_normalize
const bool _assign_zero_if_not_matched
Class QuantumGate_CPTP
Inheritance Relationships
Base Type
Class Documentation
class QuantumGate_CPTP : public QuantumGateBase

Public Functions

inline explicit QuantumGate_CPTP(std::vector<QuantumGateBase*> gate_list)
inline explicit QuantumGate_CPTP(std::vector<QuantumGateBase*> gate_list, UINT classical_register_address)
inline virtual ~QuantumGate_CPTP()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGate_CPTP *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual std::vector<QuantumGateBase*> get_gate_list()

Protected Attributes

Random random
std::vector<QuantumGateBase*> _gate_list
bool is_instrument
UINT _classical_register_address
Class QuantumGate_Probabilistic
Inheritance Relationships
Base Type
Class Documentation
class QuantumGate_Probabilistic : public QuantumGateBase

ここら辺のtarget listの仕様について ゲートをマージしたときのtargetやcontrolの挙動は get_new_qubit_list 関数で決められている Identity のゲート + 含まれるすべてのゲート のゲート集合を元に、 get_new_qubit_list で決める ただし、和が1のProbabilistic においてのみ、 Identityなしで求めている

Public Functions

inline explicit QuantumGate_Probabilistic(const std::vector<double> &distribution, const std::vector<QuantumGateBase*> &gate_list)
inline explicit QuantumGate_Probabilistic(const std::vector<double> &distribution, const std::vector<QuantumGateBase*> &gate_list, UINT classical_register_address)
inline virtual ~QuantumGate_Probabilistic()
inline virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGate_Probabilistic *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
inline virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

inline virtual void set_seed(int seed) override
inline virtual std::vector<double> get_cumulative_distribution()
inline virtual std::vector<double> get_distribution()
inline virtual std::vector<QuantumGateBase*> get_gate_list()
inline virtual void optimize_ProbablisticGate()
inline virtual bool is_noise() override

Protected Attributes

Random random
std::vector<double> _distribution
std::vector<double> _cumulative_distribution
std::vector<QuantumGateBase*> _gate_list
bool is_instrument
UINT _classical_register_address
Class QuantumGate_SingleParameter
Inheritance Relationships
Base Type
Derived Types
Class Documentation
class QuantumGate_SingleParameter : public QuantumGateBase

Subclassed by ClsParametricPauliRotationGate, QuantumGate_SingleParameterOneQubitRotation

Public Functions

inline QuantumGate_SingleParameter(double angle)
inline virtual void set_parameter_value(double value)
inline virtual double get_parameter_value() const
virtual QuantumGate_SingleParameter *copy() const override = 0

Protected Attributes

double _angle
UINT _parameter_type
Class QuantumGate_SingleParameterOneQubitRotation
Inheritance Relationships
Base Type
Derived Types
Class Documentation
class QuantumGate_SingleParameterOneQubitRotation : public QuantumGate_SingleParameter

Subclassed by ClsParametricRXGate, ClsParametricRYGate, ClsParametricRZGate

Public Functions

inline virtual void update_quantum_state(QuantumStateBase *state) override

Protected Types

using UpdateFunc = void (*)(UINT, double, CTYPE*, ITYPE)
using UpdateFuncGpu = void (*)(UINT, double, void*, ITYPE, void*, UINT)

Protected Functions

inline QuantumGate_SingleParameterOneQubitRotation(double angle)

Protected Attributes

UpdateFunc _update_func = nullptr
UpdateFunc _update_func_dm = nullptr
UpdateFuncGpu _update_func_gpu = nullptr
Class QuantumGateBase
Inheritance Relationships
Derived Types
Class Documentation
class QuantumGateBase

Subclassed by ClsNoisyEvolution, ClsNoisyEvolution_auto, ClsNoisyEvolution_fast, ClsOneControlOneTargetGate, ClsOneQubitGate, ClsOneQubitRotationGate, ClsPauliGate, ClsPauliRotationGate, ClsReversibleBooleanGate, ClsStateReflectionGate, ClsTwoQubitGate, QuantumGate_Adaptive, QuantumGate_CP, QuantumGate_CPTP, QuantumGate_Probabilistic, QuantumGate_SingleParameter, QuantumGateDiagonalMatrix, QuantumGateMatrix, QuantumGateSparseMatrix

Public Functions

inline virtual ~QuantumGateBase()
inline std::vector<UINT> get_target_index_list() const
inline std::vector<UINT> get_control_index_list() const
inline std::vector<UINT> get_control_value_list() const
inline std::vector<std::pair<UINT, UINT>> get_control_index_value_list() const
virtual void update_quantum_state(QuantumStateBase *state) = 0
virtual QuantumGateBase *copy() const = 0
virtual void set_matrix(ComplexMatrix &matrix) const = 0
bool is_commute(const QuantumGateBase *gate) const
bool is_Pauli() const
bool is_Clifford() const
bool is_Gaussian() const
bool is_parametric() const
bool is_diagonal() const
UINT get_property_value() const
bool commute_Pauli_at(UINT qubit_index, UINT pauli_type) const
virtual std::string get_name() const
virtual std::string to_string() const
virtual boost::property_tree::ptree to_ptree() const

japanese-en ptreeに変換する

Returns

ptree

inline virtual bool is_noise()
inline virtual void set_seed(int)
inline void set_target_index_list(const std::vector<UINT> &target_index_list)
inline void set_control_index_list(const std::vector<UINT> &control_index_list)
virtual QuantumGateBase *get_inverse(void) const

Public Members

std::vector<TargetQubitInfo> &target_qubit_list

ターゲット量子ビットのリスト

std::vector<ControlQubitInfo> &control_qubit_list

コントロール量子ビットのリスト

Protected Functions

inline QuantumGateBase()
inline QuantumGateBase(const QuantumGateBase &obj)
QuantumGateBase &operator=(const QuantumGateBase &rhs) = delete

Protected Attributes

std::vector<TargetQubitInfo> _target_qubit_list
std::vector<ControlQubitInfo> _control_qubit_list
UINT _gate_property = 0
std::string _name = "Generic gate"

Friends

friend std::ostream &operator<<(std::ostream &os, const QuantumGateBase&)
friend std::ostream &operator<<(std::ostream &os, const QuantumGateBase *gate)
Class QuantumGateDiagonalMatrix
Inheritance Relationships
Base Type
Class Documentation
class QuantumGateDiagonalMatrix : public QuantumGateBase

Public Functions

QuantumGateDiagonalMatrix(const std::vector<UINT> &target_qubit_index_list, const ComplexVector &matrix_element, const std::vector<UINT> &control_qubit_index_list = {})
QuantumGateDiagonalMatrix(const std::vector<UINT> &target_qubit_index_list, ComplexVector *matrix_element, const std::vector<UINT> &control_qubit_index_list = {})
QuantumGateDiagonalMatrix(const std::vector<TargetQubitInfo> &target_qubit_index_list, const ComplexVector &matrix_element, const std::vector<ControlQubitInfo> &control_qubit_index_list = {})
QuantumGateDiagonalMatrix(const std::vector<TargetQubitInfo> &target_qubit_index_list, ComplexVector *matrix_element, const std::vector<ControlQubitInfo> &control_qubit_index_list = {})
inline virtual ~QuantumGateDiagonalMatrix()
virtual void add_control_qubit(UINT qubit_index, UINT control_value)
inline virtual void multiply_scalar(CPPCTYPE value)
inline virtual void set_gate_property(UINT gate_property_)
virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGateDiagonalMatrix *copy() const override
inline virtual QuantumGateDiagonalMatrix *get_inverse(void) const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
virtual std::string to_string() const override
virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

Friends

friend std::ostream &operator<<(std::ostream &os, const QuantumGateDiagonalMatrix &gate)
friend std::ostream &operator<<(std::ostream &os, QuantumGateDiagonalMatrix *gate)
Class QuantumGateMatrix
Inheritance Relationships
Base Type
Class Documentation
class QuantumGateMatrix : public QuantumGateBase

Public Functions

QuantumGateMatrix(const std::vector<UINT> &target_qubit_index_list, const ComplexMatrix &matrix_element, const std::vector<UINT> &control_qubit_index_list = {})
QuantumGateMatrix(const std::vector<UINT> &target_qubit_index_list, ComplexMatrix *matrix_element, const std::vector<UINT> &control_qubit_index_list = {})
QuantumGateMatrix(const std::vector<TargetQubitInfo> &target_qubit_index_list, const ComplexMatrix &matrix_element, const std::vector<ControlQubitInfo> &control_qubit_index_list = {})
QuantumGateMatrix(const std::vector<TargetQubitInfo> &target_qubit_index_list, ComplexMatrix *matrix_element, const std::vector<ControlQubitInfo> &control_qubit_index_list = {})
inline virtual ~QuantumGateMatrix()
virtual void add_control_qubit(UINT qubit_index, UINT control_value)
inline virtual void multiply_scalar(CPPCTYPE value)
inline virtual void set_gate_property(UINT gate_property_)
virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGateMatrix *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
virtual std::string to_string() const override
virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

virtual QuantumGateMatrix *get_inverse(void) const override

Friends

friend std::ostream &operator<<(std::ostream &os, const QuantumGateMatrix &gate)
friend std::ostream &operator<<(std::ostream &os, QuantumGateMatrix *gate)
Class QuantumGateSparseMatrix
Inheritance Relationships
Base Type
Class Documentation
class QuantumGateSparseMatrix : public QuantumGateBase

Public Functions

QuantumGateSparseMatrix(const std::vector<UINT> &target_qubit_index_list, const SparseComplexMatrix &matrix_element, const std::vector<UINT> &control_qubit_index_list = {})
QuantumGateSparseMatrix(const std::vector<UINT> &target_qubit_index_list, SparseComplexMatrix *matrix_element, const std::vector<UINT> &control_qubit_index_list = {})
QuantumGateSparseMatrix(const std::vector<TargetQubitInfo> &target_qubit_index_list, const SparseComplexMatrix &matrix_element, const std::vector<ControlQubitInfo> &control_qubit_index_list = {})
QuantumGateSparseMatrix(const std::vector<TargetQubitInfo> &target_qubit_index_list, SparseComplexMatrix *matrix_element, const std::vector<ControlQubitInfo> &control_qubit_index_list = {})
inline virtual ~QuantumGateSparseMatrix()
virtual void add_control_qubit(UINT qubit_index, UINT control_value)
inline virtual void multiply_scalar(CPPCTYPE value)
inline virtual void set_gate_property(UINT gate_property_)
virtual void update_quantum_state(QuantumStateBase *state) override
inline virtual QuantumGateSparseMatrix *copy() const override
inline virtual void set_matrix(ComplexMatrix &matrix) const override
virtual std::string to_string() const override
virtual boost::property_tree::ptree to_ptree() const override

japanese-en ptreeに変換する

Returns

ptree

Friends

friend std::ostream &operator<<(std::ostream &os, const QuantumGateSparseMatrix &gate)
friend std::ostream &operator<<(std::ostream &os, QuantumGateSparseMatrix *gate)
Class QuantumStateBase
Inheritance Relationships
Derived Types
Class Documentation
class QuantumStateBase

Subclassed by DensityMatrixCpu, QuantumStateCpu

Public Functions

inline QuantumStateBase(UINT qubit_count_, bool is_state_vector)
inline QuantumStateBase(UINT qubit_count_, bool is_state_vector, UINT device_number_)
inline virtual ~QuantumStateBase()
inline virtual bool is_state_vector() const
virtual void set_zero_state() = 0
virtual void set_zero_norm_state() = 0
virtual void set_computational_basis(ITYPE comp_basis) = 0
virtual void set_Haar_random_state() = 0
virtual void set_Haar_random_state(UINT seed) = 0
virtual double get_zero_probability(UINT target_qubit_index) const = 0
virtual double get_marginal_probability(std::vector<UINT> measured_values) const = 0
virtual double get_entropy() const = 0
virtual double get_squared_norm() const = 0
virtual double get_squared_norm_single_thread() const = 0
virtual void normalize(double squared_norm) = 0
virtual void normalize_single_thread(double squared_norm) = 0
virtual QuantumStateBase *allocate_buffer() const = 0
virtual QuantumStateBase *copy() const = 0
virtual void load(const QuantumStateBase *state) = 0
virtual void load(const std::vector<CPPCTYPE> &state) = 0
virtual void load(const CPPCTYPE *state) = 0
virtual const std::string get_device_name() const = 0
virtual void *data() const = 0
virtual CPPCTYPE *data_cpp() const = 0
virtual CTYPE *data_c() const = 0
virtual CPPCTYPE *duplicate_data_cpp() const = 0
virtual CTYPE *duplicate_data_c() const = 0
virtual void add_state(const QuantumStateBase *state) = 0
virtual void add_state_with_coef(CPPCTYPE coef, const QuantumStateBase *state) = 0
virtual void add_state_with_coef_single_thread(CPPCTYPE coef, const QuantumStateBase *state) = 0
virtual void multiply_coef(CPPCTYPE coef) = 0
virtual void multiply_elementwise_function(const std::function<CPPCTYPE(ITYPE)> &func) = 0
inline virtual UINT get_classical_value(UINT index)
inline virtual void set_classical_value(UINT index, UINT val)
inline virtual const std::vector<UINT> get_classical_register() const
virtual std::vector<ITYPE> sampling(UINT sampling_count) = 0
virtual std::vector<ITYPE> sampling(UINT sampling_count, UINT random_seed) = 0
virtual boost::property_tree::ptree to_ptree() const = 0
inline virtual std::string to_string() const
inline virtual void *get_cuda_stream() const

Public Members

const UINT &qubit_count
const ITYPE &dim
const std::vector<UINT> &classical_register
const UINT &device_number

Protected Attributes

ITYPE _dim
UINT _qubit_count
bool _is_state_vector
std::vector<UINT> _classical_register
UINT _device_number
void *_cuda_stream

Friends

inline friend std::ostream &operator<<(std::ostream &os, const QuantumStateBase &state)
inline friend std::ostream &operator<<(std::ostream &os, const QuantumStateBase *state)
Class QuantumStateCpu
Inheritance Relationships
Base Type
Class Documentation
class QuantumStateCpu : public QuantumStateBase

Public Functions

inline explicit QuantumStateCpu(UINT qubit_count_)
inline virtual ~QuantumStateCpu()
inline virtual void set_zero_state() override
inline virtual void set_zero_norm_state() override
inline virtual void set_computational_basis(ITYPE comp_basis) override
inline virtual void set_Haar_random_state() override
inline virtual void set_Haar_random_state(UINT seed) override
inline virtual double get_zero_probability(UINT target_qubit_index) const override
inline virtual double get_marginal_probability(std::vector<UINT> measured_values) const override
inline virtual double get_entropy() const override
inline virtual double get_squared_norm() const override
inline virtual double get_squared_norm_single_thread() const override
inline virtual void normalize(double squared_norm) override
inline virtual void normalize_single_thread(double squared_norm) override
inline virtual QuantumStateCpu *allocate_buffer() const override
inline virtual QuantumStateCpu *copy() const override
inline virtual void load(const QuantumStateBase *_state) override
inline virtual void load(const std::vector<CPPCTYPE> &_state) override
inline virtual void load(const CPPCTYPE *_state) override
inline virtual const std::string get_device_name() const override
inline virtual void *data() const override
inline virtual CPPCTYPE *data_cpp() const override
inline virtual CTYPE *data_c() const override
inline virtual CTYPE *duplicate_data_c() const override
inline virtual CPPCTYPE *duplicate_data_cpp() const override
inline virtual void add_state(const QuantumStateBase *state) override
inline virtual void add_state_with_coef(CPPCTYPE coef, const QuantumStateBase *state) override
inline virtual void add_state_with_coef_single_thread(CPPCTYPE coef, const QuantumStateBase *state) override
inline virtual void multiply_coef(CPPCTYPE coef) override
inline virtual void multiply_elementwise_function(const std::function<CPPCTYPE(ITYPE)> &func) override
inline virtual std::vector<ITYPE> sampling(UINT sampling_count) override
inline virtual std::vector<ITYPE> sampling(UINT sampling_count, UINT random_seed) override
inline virtual boost::property_tree::ptree to_ptree() const override
Class QuantumStateProcessorException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class QuantumStateProcessorException : public logic_error

Public Functions

inline QuantumStateProcessorException(const std::string &message)
Class QubitIndexOutOfRangeException
Inheritance Relationships
Base Type
  • public out_of_range

Class Documentation
class QubitIndexOutOfRangeException : public out_of_range

Public Functions

inline QubitIndexOutOfRangeException(const std::string &message)
Class QubitInfo
Inheritance Relationships
Derived Types
Class Documentation
class QubitInfo

Subclassed by ControlQubitInfo, TargetQubitInfo

Public Functions

inline virtual ~QubitInfo()
inline UINT index() const
inline void set_index(int idx)
inline explicit QubitInfo(UINT index_)

Protected Attributes

UINT _index
Class Random
Class Documentation
class Random

Public Functions

inline Random()
inline void set_seed(uint64_t seed)
inline double uniform()
inline double normal()
inline unsigned long long int64()
inline unsigned long int32()
Class RegressionProblem
Class Documentation
class RegressionProblem

Public Functions

inline RegressionProblem(std::vector<std::vector<double>> input_data, std::vector<std::vector<double>> output_data)
inline virtual UINT get_input_dim() const
inline virtual std::vector<double> get_input_data(UINT sample_id) const
inline virtual UINT get_output_dim() const
inline virtual std::vector<double> get_output_data(UINT sample_id)
inline virtual double compute_loss(UINT sample_id, std::vector<double> prediction)

Protected Attributes

std::function<double(std::vector<double>, std::vector<double>)> _loss_function = loss_function::L2_distance<double>
std::vector<std::vector<double>> _input_data
std::vector<std::vector<double>> _output_data
Class SinglePauliOperator
Class Documentation
class SinglePauliOperator

Public Functions

inline SinglePauliOperator(UINT index_, UINT pauli_id_)
inline UINT index() const
inline UINT pauli_id() const
inline boost::property_tree::ptree to_ptree() const

Protected Attributes

UINT _index
UINT _pauli_id
Class TargetQubitInfo
Inheritance Relationships
Base Type
Class Documentation
class TargetQubitInfo : public QubitInfo

Public Functions

inline TargetQubitInfo(void)
inline explicit TargetQubitInfo(UINT index_)
inline TargetQubitInfo(UINT index_, UINT commutation_property_)
inline bool is_commute_X() const
inline bool is_commute_Y() const
inline bool is_commute_Z() const
virtual bool is_commute_with(const TargetQubitInfo &info) const
virtual bool is_commute_with(const ControlQubitInfo &info) const
inline virtual UINT get_merged_property(UINT property) const
inline virtual UINT get_merged_property(const TargetQubitInfo &target) const
inline virtual UINT get_merged_property(const ControlQubitInfo &control) const
Class Timer
Class Documentation
class Timer

Public Functions

inline Timer()
inline void reset()
inline double elapsed()
inline void temporal_stop()
inline void temporal_resume()
Class UndefinedUpdateFuncException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class UndefinedUpdateFuncException : public logic_error

Public Functions

inline UndefinedUpdateFuncException(const std::string &message)
Class UnionFind
Class Documentation
class UnionFind

Public Functions

inline explicit UnionFind(int N)
inline int root(int A)
inline bool same(int A, int B)
inline int size(int A)
inline bool connect(int A, int B)
Class UnknownPTreePropertyValueException
Inheritance Relationships
Base Type
  • public logic_error

Class Documentation
class UnknownPTreePropertyValueException : public logic_error

Public Functions

inline UnknownPTreePropertyValueException(const std::string &message)
Functions
Function bidiagonalize_real_matrix_pair_with_symmetric_products
Function Documentation
std::tuple<Eigen::Matrix4cd, Eigen::Matrix4cd> bidiagonalize_real_matrix_pair_with_symmetric_products(Eigen::Matrix4d matA, Eigen::Matrix4d matB)
Function bidiagonalize_unitary_with_special_orthogonals
Function Documentation
std::tuple<Eigen::Matrix4cd, Eigen::Matrix4cd, Eigen::Matrix4cd> bidiagonalize_unitary_with_special_orthogonals(Eigen::Matrix4cd mat)
Function check_is_unique_index_list
Function Documentation
bool check_is_unique_index_list(const std::vector<UINT> &index_list)
Function check_Pauli_operator
Function Documentation
bool check_Pauli_operator(const GeneralQuantumOperator *quantum_operator, const PauliOperator *pauli_operator)
Function chfmt
Function Documentation
void chfmt(std::string &ops)
Function circuit::from_ptree
Function Documentation
QuantumCircuit *circuit::from_ptree(const boost::property_tree::ptree &pt)
Function circuit::parametric_circuit_from_ptree
Function Documentation
ParametricQuantumCircuit *circuit::parametric_circuit_from_ptree(const boost::property_tree::ptree &pt)
Function convert_observable_to_matrix
Function Documentation
ComplexMatrix convert_observable_to_matrix(const HermitianQuantumOperator &observable)
Function count_population_cpp
Function Documentation
static inline UINT count_population_cpp(ITYPE x)
Function CSD
Function Documentation
std::vector<QuantumGateBase*> CSD(QuantumGateBase *target_gate)
Function CSD_internal
Function Documentation
void CSD_internal(ComplexMatrix mat, std::vector<UINT> now_control_qubits, std::vector<UINT> all_control_qubits, int ban, std::vector<QuantumGateBase*> &CSD_gate_list)
Function gate::Adaptive(QuantumGateBase *, std::function<bool(const std::vector<UINT>&)>)
Function Documentation
QuantumGateBase *gate::Adaptive(QuantumGateBase *gate, std::function<bool(const std::vector<UINT>&)> func)
Function gate::Adaptive(QuantumGateBase *, std::function<bool(const std::vector<UINT>&, UINT)>, UINT)
Function Documentation
QuantumGateBase *gate::Adaptive(QuantumGateBase *gate, std::function<bool(const std::vector<UINT>&, UINT)> func, UINT id)
Function gate::add(const QuantumGateBase *, const QuantumGateBase *)
Function Documentation
QuantumGateMatrix *gate::add(const QuantumGateBase *gate1, const QuantumGateBase *gate2)
Function gate::add(std::vector<QuantumGateBase *>)
Function Documentation
QuantumGateMatrix *gate::add(std::vector<QuantumGateBase*> gate_list)
Function gate::AmplitudeDampingNoise
Function Documentation
QuantumGate_CPTP *gate::AmplitudeDampingNoise(UINT target_index, double prob)

Amplitude damping noiseを発生させるゲート

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • prob[in] エラーが生じる確率

Returns

作成されたゲートのインスタンス

Function gate::BitFlipNoise
Function Documentation
QuantumGate_Probabilistic *gate::BitFlipNoise(UINT target_index, double prob)

bit-flipノイズを発生させるゲート

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • prob[in] エラーが生じる確率

Returns

作成されたゲートのインスタンス

Function gate::CNOT
Function Documentation
ClsOneControlOneTargetGate *gate::CNOT(UINT control_qubit_index, UINT target_qubit_index)
Function gate::CP
Function Documentation
QuantumGateBase *gate::CP(std::vector<QuantumGateBase*> gate_list, bool state_normalize, bool probability_normalize, bool assign_zero_if_not_matched)
Function gate::CPTP
Function Documentation
QuantumGateBase *gate::CPTP(std::vector<QuantumGateBase*> gate_list)
Function gate::create_parametric_quantum_gate_from_string
Function Documentation
QuantumGateBase *gate::create_parametric_quantum_gate_from_string(std::string gate_string)
Function gate::create_quantum_gate_from_string
Function Documentation
QuantumGateBase *gate::create_quantum_gate_from_string(std::string gate_string)
Function gate::CZ
Function Documentation
ClsOneControlOneTargetGate *gate::CZ(UINT control_qubit_index, UINT target_qubit_index)
Function gate::DenseMatrix(UINT, ComplexMatrix)
Function Documentation
QuantumGateMatrix *gate::DenseMatrix(UINT target_qubit_index, ComplexMatrix matrix)

\(n\)-qubit 行列を用いて1-qubitゲートを生成する。

Parameters
  • target_qubit_index[in] ターゲットとなる量子ビットの添え字

  • matrix[in] 作用するゲートの \(2\times 2\)の複素行列

Returns

作成されたゲートのインスタンス

Function gate::DenseMatrix(std::vector<UINT>, ComplexMatrix)
Function Documentation
QuantumGateMatrix *gate::DenseMatrix(std::vector<UINT> target_qubit_index_list, ComplexMatrix matrix)

\(n\)-qubit 行列を用いてn-qubitゲートを生成する。

target_qubit_index_listの要素数を \(m\)としたとき、matrix\(2^m \times 2^m \)の複素行列でなくてはいけない。

Parameters
  • target_qubit_index_list[in] ターゲットとなる量子ビットの添え字

  • matrix[in] 作用するゲートの複素行列。

Returns

作成されたゲートのインスタンス

Function gate::DephasingNoise
Function Documentation
QuantumGate_Probabilistic *gate::DephasingNoise(UINT target_index, double prob)

phase-flipノイズを発生させるゲート

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • prob[in] エラーが生じる確率

Returns

作成されたゲートのインスタンス

Function gate::DepolarizingNoise
Function Documentation
QuantumGate_Probabilistic *gate::DepolarizingNoise(UINT target_index, double prob)

Depolarizin noiseを発生させるゲート

X,Y,Zがそれぞれprob/3の確率で生じる。

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • prob[in] エラーが生じる確率

Returns

作成されたゲートのインスタンス

Function gate::DiagonalMatrix
Function Documentation
QuantumGateDiagonalMatrix *gate::DiagonalMatrix(std::vector<UINT> target_qubit_index_list, ComplexVector diagonal_element)

\(n\)-qubit 対角な行列を用いてn-qubitゲートを生成する。

target_qubit_index_listの要素数を \(m\)としたとき、matrix\(2^m \times 2^m \)の複素行列でなくてはいけない。

Parameters
  • target_qubit_index_list[in] ターゲットとなる量子ビットの添え字

  • matrix[in] 作用するゲートの複素行列の対角成分。

Returns

作成されたゲートのインスタンス

Function gate::from_ptree
Function Documentation
QuantumGateBase *gate::from_ptree(const boost::property_tree::ptree &pt)
Function gate::get_adjoint_gate
Function Documentation
QuantumGateMatrix *gate::get_adjoint_gate(const QuantumGateBase *gate)
Function gate::get_conjugate_gate
Function Documentation
QuantumGateMatrix *gate::get_conjugate_gate(const QuantumGateBase *gate)
Function gate::get_extended_matrix
Function Documentation
void gate::get_extended_matrix(const QuantumGateBase *gate, const std::vector<TargetQubitInfo> &new_target_list, const std::vector<ControlQubitInfo> &new_control_list, ComplexMatrix &matrix)
Function gate::get_new_qubit_list
Function Documentation
void gate::get_new_qubit_list(const QuantumGateBase *gate_first, const QuantumGateBase *gate_second, std::vector<TargetQubitInfo> &new_target_list, std::vector<ControlQubitInfo> &new_control_list)
Function gate::get_transpose_gate
Function Documentation
QuantumGateMatrix *gate::get_transpose_gate(const QuantumGateBase *gate)
Function gate::H
Function Documentation
ClsOneQubitGate *gate::H(UINT qubit_index)
Function gate::Identity
Function Documentation
ClsOneQubitGate *gate::Identity(UINT qubit_index)
Function gate::IndependentXZNoise
Function Documentation
QuantumGate_Probabilistic *gate::IndependentXZNoise(UINT target_index, double prob)

bit-flipとphase-flipを同じ確率でノイズを発生させるゲート

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • prob[in] エラーが生じる確率

Returns

作成されたゲートのインスタンス

Function gate::Instrument
Function Documentation
QuantumGateBase *gate::Instrument(std::vector<QuantumGateBase*> gate_list, UINT classical_register_address)
Function gate::Measurement
Function Documentation
QuantumGate_Instrument *gate::Measurement(UINT target_index, UINT classical_register_address)

測定を行う

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • classical_register_address[in] 測定値を格納する古典レジスタの場所

Returns

作成されたゲートのインスタンス

Function gate::merge(const QuantumGateBase *, const QuantumGateBase *)
Function Documentation
QuantumGateMatrix *gate::merge(const QuantumGateBase *gate_applied_first, const QuantumGateBase *gate_applied_later)
Function gate::merge(std::vector<QuantumGateBase *>)
Function Documentation
QuantumGateMatrix *gate::merge(std::vector<QuantumGateBase*> gate_list)
Function gate::NoisyEvolution
Function Documentation
ClsNoisyEvolution *gate::NoisyEvolution(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time, double dt = 1e-6)

Noisy Evolution TODO: do this comment

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • classical_register_address[in] 測定値を格納する古典レジスタの場所

Returns

作成されたゲートのインスタンス

Function gate::NoisyEvolution_auto
Function Documentation
ClsNoisyEvolution_auto *gate::NoisyEvolution_auto(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time)

Noisy Evolution TODO: do this comment

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • classical_register_address[in] 測定値を格納する古典レジスタの場所

Returns

作成されたゲートのインスタンス

Function gate::NoisyEvolution_fast
Function Documentation
ClsNoisyEvolution_fast *gate::NoisyEvolution_fast(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time)

Noisy Evolution TODO: do this comment

Parameters
  • target_index[in] ターゲットとなる量子ビットの添え字

  • classical_register_address[in] 測定値を格納する古典レジスタの場所

Returns

作成されたゲートのインスタンス

Function gate::P0
Function Documentation
ClsOneQubitGate *gate::P0(UINT qubit_index)
Function gate::P1
Function Documentation
ClsOneQubitGate *gate::P1(UINT qubit_index)
Function gate::parametric_gate_from_ptree
Function Documentation
QuantumGate_SingleParameter *gate::parametric_gate_from_ptree(const boost::property_tree::ptree &pt)
Function gate::ParametricPauliRotation
Function Documentation
QuantumGate_SingleParameter *gate::ParametricPauliRotation(std::vector<UINT> target, std::vector<UINT> pauli_id, double initial_angle = 0.)
Function gate::ParametricRX
Function Documentation
QuantumGate_SingleParameter *gate::ParametricRX(UINT qubit_index, double initial_angle = 0.)
Function gate::ParametricRY
Function Documentation
QuantumGate_SingleParameter *gate::ParametricRY(UINT qubit_index, double initial_angle = 0.)
Function gate::ParametricRZ
Function Documentation
QuantumGate_SingleParameter *gate::ParametricRZ(UINT qubit_index, double initial_angle = 0.)
Function gate::Pauli
Function Documentation
ClsPauliGate *gate::Pauli(std::vector<UINT> target_qubit_index_list, std::vector<UINT> pauli_id_list)

\(n\)-qubit パウリ演算子のゲートを作成する

例えば \(Y_1 X_3\)であれば、target_qubit_index_list = {1,3}, pauli_id_list = {2,1};である。

Parameters
  • target_qubit_index_list[in] ターゲットとなる量子ビットの添え字のリスト

  • pauli_id_list[in] その量子ビットに作用するパウリ演算子。 \({I,X,Y,Z}\)\({0,1,2,3}\)に対応する。

Returns

作成されたゲートのインスタンス

Function gate::PauliRotation
Function Documentation
ClsPauliRotationGate *gate::PauliRotation(std::vector<UINT> target_qubit_index_list, std::vector<UINT> pauli_id_list, double angle)

\(n\)-qubit パウリ演算子の回転ゲートを作成する

例えば \(Y_1 X_3\)であれば、target_qubit_index_list = {1,3}, pauli_id_list = {2,1};である。

Parameters
  • target_qubit_index_list[in] ターゲットとなる量子ビットの添え字のリスト

  • pauli_id_list[in] その量子ビットに作用するパウリ演算子。 \({I,X,Y,Z}\)\({0,1,2,3}\)に対応する。

  • angle[in] 回転角

Returns

作成されたゲートのインスタンス

Function gate::Probabilistic
Function Documentation
QuantumGateBase *gate::Probabilistic(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list)
Function gate::ProbabilisticInstrument
Function Documentation
QuantumGateBase *gate::ProbabilisticInstrument(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list, UINT classical_register_address)
Function gate::RandomUnitary(std::vector<UINT>)
Function Documentation
QuantumGateMatrix *gate::RandomUnitary(std::vector<UINT> target_qubit_index_list)

\(n\)-qubit のランダムユニタリゲートを作成する。

Parameters
  • target_qubit_index_list[in] ターゲットとなる量子ビットの添え字

  • seed[in] 乱数のシード値

Returns

作成されたゲートのインスタンス

Function gate::RandomUnitary(std::vector<UINT>, UINT)
Function Documentation
QuantumGateMatrix *gate::RandomUnitary(std::vector<UINT> target_qubit_index_list, UINT seed)
Function gate::ReversibleBoolean
Function Documentation
ClsReversibleBooleanGate *gate::ReversibleBoolean(std::vector<UINT> target_qubit_index_list, std::function<ITYPE(ITYPE, ITYPE)>)

\(n\)-qubit の可逆古典回路を作用する。

Parameters
  • target_qubit_index_list[in] ターゲットとなる量子ビットの添え字

  • function_ptr[in] 可逆古典回路の動作をする関数

Returns

作成されたゲートのインスタンス

Function gate::RotInvX
Function Documentation
ClsOneQubitRotationGate *gate::RotInvX(UINT qubit_index, double angle)
Function gate::RotInvY
Function Documentation
ClsOneQubitRotationGate *gate::RotInvY(UINT qubit_index, double angle)
Function gate::RotInvZ
Function Documentation
ClsOneQubitRotationGate *gate::RotInvZ(UINT qubit_index, double angle)
Function gate::RotX
Function Documentation
ClsOneQubitRotationGate *gate::RotX(UINT qubit_index, double angle)
Function gate::RotY
Function Documentation
ClsOneQubitRotationGate *gate::RotY(UINT qubit_index, double angle)
Function gate::RotZ
Function Documentation
ClsOneQubitRotationGate *gate::RotZ(UINT qubit_index, double angle)
Function gate::RX
Function Documentation
ClsOneQubitRotationGate *gate::RX(UINT qubit_index, double angle)
Function gate::RY
Function Documentation
ClsOneQubitRotationGate *gate::RY(UINT qubit_index, double angle)
Function gate::RZ
Function Documentation
ClsOneQubitRotationGate *gate::RZ(UINT qubit_index, double angle)
Function gate::S
Function Documentation
ClsOneQubitGate *gate::S(UINT qubit_index)
Function gate::Sdag
Function Documentation
ClsOneQubitGate *gate::Sdag(UINT qubit_index)
Function gate::SparseMatrix
Function Documentation
QuantumGateSparseMatrix *gate::SparseMatrix(std::vector<UINT> target_qubit_index_list, SparseComplexMatrix matrix)

\(n\)-qubit スパースな行列を用いてn-qubitゲートを生成する。

target_qubit_index_listの要素数を \(m\)としたとき、matrix\(2^m \times 2^m \)の複素行列でなくてはいけない。

Parameters
  • target_qubit_index_list[in] ターゲットとなる量子ビットの添え字

  • matrix[in] 作用するゲートの複素行列。

Returns

作成されたゲートのインスタンス

Function gate::sqrtX
Function Documentation
ClsOneQubitGate *gate::sqrtX(UINT qubit_index)
Function gate::sqrtXdag
Function Documentation
ClsOneQubitGate *gate::sqrtXdag(UINT qubit_index)
Function gate::sqrtY
Function Documentation
ClsOneQubitGate *gate::sqrtY(UINT qubit_index)
Function gate::sqrtYdag
Function Documentation
ClsOneQubitGate *gate::sqrtYdag(UINT qubit_index)
Function gate::StateReflection
Function Documentation
ClsStateReflectionGate *gate::StateReflection(const QuantumState *reflection_state)

量子状態に対して量子状態を反射する。

Parameters

reflection_state[in] 反射に用いられる量子状態

Returns

作成されたゲートのインスタンス

Function gate::SWAP
Function Documentation
ClsTwoQubitGate *gate::SWAP(UINT qubit_index1, UINT qubit_index2)
Function gate::T
Function Documentation
ClsOneQubitGate *gate::T(UINT qubit_index)
Function gate::Tdag
Function Documentation
ClsOneQubitGate *gate::Tdag(UINT qubit_index)
Function gate::to_matrix_gate
Function Documentation
QuantumGateMatrix *gate::to_matrix_gate(const QuantumGateBase *gate)
Function gate::TwoQubitDepolarizingNoise
Function Documentation
QuantumGate_Probabilistic *gate::TwoQubitDepolarizingNoise(UINT target_index1, UINT target_index2, double prob)

Two-qubit depolarizin noiseを発生させるゲート

IIを除くtwo qubit Pauli operationがそれぞれprob/15の確率で生じる。

Parameters
  • target_index1[in] ターゲットとなる量子ビットの添え字

  • target_index2[in] ターゲットとなる量子ビットの添え字

  • prob[in] エラーが生じる確率

Returns

作成されたゲートのインスタンス

Function gate::U1
Function Documentation
QuantumGateMatrix *gate::U1(UINT qubit_index, double lambda)
Function gate::U2
Function Documentation
QuantumGateMatrix *gate::U2(UINT qubit_index, double phi, double lambda)
Function gate::U3
Function Documentation
QuantumGateMatrix *gate::U3(UINT qubit_index, double theta, double phi, double lambda)
Function gate::X
Function Documentation
ClsOneQubitGate *gate::X(UINT qubit_index)
Function gate::Y
Function Documentation
ClsOneQubitGate *gate::Y(UINT qubit_index)
Function gate::Z
Function Documentation
ClsOneQubitGate *gate::Z(UINT qubit_index)
Function get_Pauli_matrix
Function Documentation
void get_Pauli_matrix(ComplexMatrix &matrix, const std::vector<UINT> &pauli_id_list)
Function Igate_idling
Function Documentation
static void Igate_idling(UINT, CTYPE*, ITYPE)
Function Igate_idling_gpu
Function Documentation
static void Igate_idling_gpu(UINT, void*, ITYPE, void*, UINT)
Function KAK_decomposition
Function Documentation
KAK_data KAK_decomposition(QuantumGateBase *target_gate, std::vector<UINT> target_bits)
Function KAK_decomposition_internal
Function Documentation
KAK_data KAK_decomposition_internal(QuantumGateBase *target_gate)
Function loss_function::cross_entropy
Function Documentation
double loss_function::cross_entropy(const std::vector<double> &prediction, const std::vector<double> &correct_label)
Template Function loss_function::L2_distance
Function Documentation
template<typename T>
double loss_function::L2_distance(const std::vector<T> &s1, const std::vector<T> &s2)
Function loss_function::softmax_cross_entropy
Function Documentation
double loss_function::softmax_cross_entropy(const std::vector<double> &prediction, const std::vector<double> &correct_label)
Function loss_function::softmax_cross_entropy_category
Function Documentation
double loss_function::softmax_cross_entropy_category(std::vector<double> prediction, UINT correct_label)
Function observable::create_observable_from_openfermion_file
Function Documentation
HermitianQuantumOperator *observable::create_observable_from_openfermion_file(std::string file_path)
Function observable::create_observable_from_openfermion_text
Function Documentation
HermitianQuantumOperator *observable::create_observable_from_openfermion_text(const std::string &text)
Function observable::create_split_observable
Function Documentation
std::pair<HermitianQuantumOperator*, HermitianQuantumOperator*> observable::create_split_observable(std::string file_path)
Function observable::from_ptree
Function Documentation
HermitianQuantumOperator *observable::from_ptree(const boost::property_tree::ptree &pt)
Function parse_openfermion_line
Function Documentation
std::tuple<double, double, std::string> parse_openfermion_line(std::string line)
Function ptree::complex_array_from_ptree
Function Documentation
std::vector<CPPCTYPE> ptree::complex_array_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::complex_from_ptree
Function Documentation
CPPCTYPE ptree::complex_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::complex_matrix_from_ptree
Function Documentation
ComplexMatrix ptree::complex_matrix_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::complex_vector_from_ptree
Function Documentation
ComplexVector ptree::complex_vector_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::control_qubit_list_from_ptree
Function Documentation
std::vector<ControlQubitInfo> ptree::control_qubit_list_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::from_json
Function Documentation
boost::property_tree::ptree ptree::from_json(const std::string &json)
Function ptree::ptree_array_from_ptree
Function Documentation
std::vector<boost::property_tree::ptree> ptree::ptree_array_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::sparse_complex_matrix_from_ptree
Function Documentation
SparseComplexMatrix ptree::sparse_complex_matrix_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::target_qubit_list_from_ptree
Function Documentation
std::vector<TargetQubitInfo> ptree::target_qubit_list_from_ptree(const boost::property_tree::ptree &pt)
Function ptree::to_json
Function Documentation
std::string ptree::to_json(const boost::property_tree::ptree &ptree)
Function ptree::to_ptree(const CPPCTYPE&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const CPPCTYPE &cnum)
Function ptree::to_ptree(const std::vector<UINT>&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const std::vector<UINT> &uarray)
Function ptree::to_ptree(const std::vector<CPPCTYPE>&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const std::vector<CPPCTYPE> &carray)
Function ptree::to_ptree(const std::vector<boost::property_tree::ptree>&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const std::vector<boost::property_tree::ptree> &pt_array)
Function ptree::to_ptree(const std::vector<TargetQubitInfo>&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const std::vector<TargetQubitInfo> &target_qubit_list)
Function ptree::to_ptree(const std::vector<ControlQubitInfo>&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const std::vector<ControlQubitInfo> &control_qubit_list)
Function ptree::to_ptree(const ComplexVector&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const ComplexVector &vector)
Function ptree::to_ptree(const ComplexMatrix&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const ComplexMatrix &matrix)
Function ptree::to_ptree(const SparseComplexMatrix&)
Function Documentation
boost::property_tree::ptree ptree::to_ptree(const SparseComplexMatrix &sparse_matrix)
Function ptree::uint_array_from_ptree
Function Documentation
std::vector<UINT> ptree::uint_array_from_ptree(const boost::property_tree::ptree &pt)
Function quantum_operator::create_general_quantum_operator_from_openfermion_file
Function Documentation
GeneralQuantumOperator *quantum_operator::create_general_quantum_operator_from_openfermion_file(std::string file_path)
Function quantum_operator::create_general_quantum_operator_from_openfermion_text
Function Documentation
GeneralQuantumOperator *quantum_operator::create_general_quantum_operator_from_openfermion_text(std::string text)
Function quantum_operator::create_split_general_quantum_operator
Function Documentation
std::pair<GeneralQuantumOperator*, GeneralQuantumOperator*> quantum_operator::create_split_general_quantum_operator(std::string file_path)
Function quantum_operator::from_ptree
Function Documentation
GeneralQuantumOperator *quantum_operator::from_ptree(const boost::property_tree::ptree &pt)
Function quantum_operator::pauli_operator_from_ptree
Function Documentation
PauliOperator *quantum_operator::pauli_operator_from_ptree(const boost::property_tree::ptree &pt)
Function quantum_operator::single_pauli_operator_from_ptree
Function Documentation
SinglePauliOperator *quantum_operator::single_pauli_operator_from_ptree(const boost::property_tree::ptree &pt)
Function rtrim
Function Documentation
std::string &rtrim(std::string &str)
Function so4_to_magic_su2s
Function Documentation
std::pair<Eigen::Matrix<CPPCTYPE, 2, 2>, Eigen::Matrix<CPPCTYPE, 2, 2>> so4_to_magic_su2s(Eigen::Matrix4cd mat)
Function split
Function Documentation
std::vector<std::string> split(const std::string &s, const std::string &delim)
Function state::drop_qubit
Function Documentation
QuantumState *state::drop_qubit(const QuantumState *state, std::vector<UINT> target, std::vector<UINT> projection)
Function state::from_ptree
Function Documentation
QuantumStateBase *state::from_ptree(const boost::property_tree::ptree &pt)
Function state::inner_product
Function Documentation
CPPCTYPE state::inner_product(const QuantumState *state_bra, const QuantumState *state_ket)
Function state::make_mixture
Function Documentation
DensityMatrixCpu *state::make_mixture(CPPCTYPE prob1, const QuantumStateBase *state1, CPPCTYPE prob2, const QuantumStateBase *state2)
Function state::make_superposition
Function Documentation
QuantumState *state::make_superposition(CPPCTYPE coef1, const QuantumState *state1, CPPCTYPE coef2, const QuantumState *state2)
Function state::partial_trace(const QuantumStateCpu *, std::vector<UINT>)
Function Documentation
DensityMatrixCpu *state::partial_trace(const QuantumStateCpu *state, std::vector<UINT> target)
Function state::partial_trace(const DensityMatrixCpu *, std::vector<UINT>)
Function Documentation
DensityMatrixCpu *state::partial_trace(const DensityMatrixCpu *state, std::vector<UINT> target_traceout)
Function state::permutate_qubit(const QuantumState *, std::vector<UINT>)
Function Documentation
QuantumState *state::permutate_qubit(const QuantumState *state, std::vector<UINT> qubit_order)
Function state::permutate_qubit(const DensityMatrixCpu *, std::vector<UINT>)
Function Documentation
DensityMatrixCpu *state::permutate_qubit(const DensityMatrixCpu *state, std::vector<UINT> qubit_order)
Function state::tensor_product(const QuantumState *, const QuantumState *)
Function Documentation
QuantumState *state::tensor_product(const QuantumState *state_left, const QuantumState *state_right)
Function state::tensor_product(const DensityMatrixCpu *, const DensityMatrixCpu *)
Function Documentation
DensityMatrixCpu *state::tensor_product(const DensityMatrixCpu *state_bra, const DensityMatrixCpu *state_ket)
Function to_general_quantum_operator
Function Documentation
GeneralQuantumOperator *to_general_quantum_operator(const QuantumGateBase *gate, UINT GQO_qubits, double tol = 1e-6)
Variables
Variable invalid_qubit
Variable Documentation
const UINT invalid_qubit = 9999
Variable KAK_GAMMA
Variable Documentation
Eigen::Matrix4cd KAK_GAMMA = (Eigen::Matrix4cd() << 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1).finished() * 0.25
Variable KAK_MAGIC
Variable Documentation
Eigen::Matrix4cd KAK_MAGIC = (Eigen::Matrix4cd() << 1, 0, 0, 1i, 0, 1i, 1, 0, 0, 1i, -1, 0, 1, 0, 0, -1i).finished() * sqrt(0.5)
Variable KAK_MAGIC_DAG
Variable Documentation
Eigen::Matrix4cd KAK_MAGIC_DAG = (Eigen::Matrix4cd() << 1, 0, 0, 1, 0, -1i, -1i, 0, 0, 1, -1, 0, -1i, 0, 0, 1i).finished() * sqrt(0.5)
Defines
Define _USE_MATH_DEFINES
Define Documentation
_USE_MATH_DEFINES
Define BOOST_BIND_GLOBAL_PLACEHOLDERS
Define Documentation
BOOST_BIND_GLOBAL_PLACEHOLDERS
Define DllExport
Define Documentation
DllExport
Define FLAG_CLIFFORD
Define Documentation
FLAG_CLIFFORD

Flgas for gate property: gate is Clifford.

Define FLAG_GAUSSIAN
Define Documentation
FLAG_GAUSSIAN

Flgas for gate property: gate is Gaussian.

Define FLAG_PARAMETRIC
Define Documentation
FLAG_PARAMETRIC

Flgas for gate property: gate is parametrized.

Define FLAG_PAULI
Define Documentation
FLAG_PAULI

Flgas for gate property: gate is Pauli.

Regulation for argument/qubit/index ordering Read this before treating kronecker product

&#8212; arguments &#8212; Arguments of create_gate_*** function must be ordered as [control qubit (list), target qubit (list), rotation angle, state, dimension]

E.g. arguments of controlled gate must be ordered as [control qubit, target qubit]. CNOT_gate(0,1) = gate_from_string(“CNOT 0 1”) = control-0 X-1 gate

When we perform gate->add_control(i, value), the operation is performed on the index where its i-th bit is value, i.e. if (index&(1ULL<<i) != 0)

&#8212; state &#8212; In C/C++, it is useful to order the computational basis so that the RIGHTmost bit is the lowest bit. e.g. state = [ state[0b00], state[0b01], state[0b10], state[0b11] ]

In quantum circuit, we call the TOP-line qubit as the FIRST qubit.

In the braket representation, we consider the RIGHTmost bit in ket represents the FIRST (or TOP-line) qubit in the quantum circuit. state[0b01] = <01|state|01> = the probability with which the TOP-qubit is one, and the second-top qubit is zero.

&#8212; gate &#8212; To be consistent with the above index ordering, the order of tensor product is *** REVERSED ***.

X_0 has matrix representation : X_0 = I \otimes X = np.kron(I,X) = [0,1,0,0] |00> state[00] [1,0,0,0] |01> state[01] [0,0,0,1] |10> state[10] [0,0,1,0] |11> state[11]

CNOT(0,1) = control-0 target-NOT-1 has matrix representation [1,0,0,0] |00> [0,0,0,1] |01> [0,0,1,0] |10> [0,1,0,0] |11>

X_0 Y_1 Z_2 = np.kron(Z_2, np.kron(Y1, X0))

Define FLAG_X_COMMUTE
Define Documentation
FLAG_X_COMMUTE

Flags for bit property: diagonal in X-basis.

Define FLAG_Y_COMMUTE
Define Documentation
FLAG_Y_COMMUTE

Flags for bit property: diagonal in Y-basis.

Define FLAG_Z_COMMUTE
Define Documentation
FLAG_Z_COMMUTE

Flags for bit property: diagonal in Z-basis.

Typedefs
Typedef ComplexMatrix
Typedef Documentation
using ComplexMatrix = Eigen::Matrix<CPPCTYPE, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>
Typedef ComplexVector
Typedef Documentation
using ComplexVector = Eigen::VectorXcd
Typedef CPPCTYPE
Typedef Documentation
using CPPCTYPE = std::complex<double>
Typedef DensityMatrix
Typedef Documentation
using DensityMatrix = DensityMatrixCpu
Typedef Observable
Typedef Documentation
using Observable = HermitianQuantumOperator
Typedef Observable
Typedef Documentation
using Observable = HermitianQuantumOperator
Typedef Observable
Typedef Documentation
using Observable = HermitianQuantumOperator
Typedef QuantumGate_Instrument
Typedef Documentation
using QuantumGate_Instrument = QuantumGate_CPTP
Typedef QuantumGate_OneControlOneTarget
Typedef Documentation
using QuantumGate_OneControlOneTarget = ClsOneControlOneTargetGate
Typedef QuantumGate_OneQubit
Typedef Documentation
using QuantumGate_OneQubit = ClsOneQubitGate
Typedef QuantumGate_OneQubitRotation
Typedef Documentation
using QuantumGate_OneQubitRotation = ClsOneQubitRotationGate
Typedef QuantumGate_ProbabilisticInstrument
Typedef Documentation
using QuantumGate_ProbabilisticInstrument = QuantumGate_Probabilistic

This type alias is kept for backward compatibility. Do not edit this!

Typedef QuantumGate_TwoQubit
Typedef Documentation
using QuantumGate_TwoQubit = ClsTwoQubitGate
Typedef QuantumState
Typedef Documentation
using QuantumState = QuantumStateCpu
Typedef SparseComplexMatrix
Typedef Documentation
using SparseComplexMatrix = Eigen::SparseMatrix<CPPCTYPE>

Contributing to Qulacs

Contributions are welcome, and they are greatly appreciated!

You can contribute in many ways:

Types of Contributions

Report Bugs

Report bugs at https://github.com/qulacs/qulacs/issues.

If you are reporting a bug, please include:

  • Your operating system name and version.

  • Any details about your local setup that might be helpful in troubleshooting.

  • Detailed steps to reproduce the bug.

Fix Bugs

Look through the GitHub issues for bugs. Anything tagged with “bug” and “help wanted” is open to whoever wants to implement it.

Implement Features

Look through the GitHub issues for features. Anything tagged with “enhancement” and “help wanted” is open to whoever wants to implement it.

Write Documentation

Qulacs could always use more documentation, whether as part of the official Qulacs docs, in docstrings, or even on the web in blog posts, articles, and such.

Submit Feedback

The best way to send feedback is to file an issue at qulacs issues.

If you are proposing a feature:

  • Explain in detail how it would work.

  • Keep the scope as narrow as possible, to make it easier to implement.

  • Remember that this is a volunteer-driven project, and that contributions are welcome :)

Get Started!

Ready to contribute? Here’s how to set up Qulacs for local development.

  1. Fork the Qulacs repo on GitHub.

  2. Clone your fork locally:

$ git clone git@github.com:qulacs/qulacs.git
  1. Create a branch for local development:

$ git checkout -b name-of-your-bugfix-or-feature

Now you can make your changes locally.

  1. When you’re done making changes, check that your changes pass flake8 and the tests, including testing other Python versions with tox:

To get flake8 and tox, just pip install them into your virtualenv.

  1. Commit your changes and push your branch to GitHub:

$ git add .
$ git commit -m "Your detailed description of your changes."
$ git push origin name-of-your-bugfix-or-feature
  1. Submit a pull request through the GitHub website.

Pull Request Guidelines

Before you submit a pull request, check that it meets these guidelines:

  1. The pull request should include tests.

  2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.md.

  3. The pull request should work for both python and C++.