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, and NTT.
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¶
Multi-thread benchmark¶
GPU 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
.
However, typically this option also affects the parallelization of other libraries.
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:
Create an empty project.
Select
x64
as an active solution platform.Right Click your project name in Solution Explorer, and select
Properties
.At
VC++ Directories
section, add the full path to./qulacs/include
toInclude Directories
At
VC++ Directories
section, add the full path to./qulacs/lib
toLibrary Directories
At
C/C++
->Code Generation
section, changeRuntime library
toMulti-threaded (/MT)
.At
Linker
->Input
section, addvqcsim_static.lib;cppsim_static.lib;csim_static.lib;
toAdditional 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 toload
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
ofQuantumState
creates superpositon, butadd_state
ofDensityMatrix
create mixed stateThe operation corresponding to
multiply_coef(z)
ofQuantumState
ismultiply_coef(abs(z)**2)
forDensityMatrix
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
set up the system to be interacted with by the environment as a Hamiltonian and specify the operator of the interaction.
specify the value to be evolved in time and the time to be varied microscopically.
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.
[ ]:
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)
[ ]:
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)
[ ]:
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 withCausalConeSimulator
.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¶
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\))
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.
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\).
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>\))
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).
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.
Obtain the \(\theta=\theta^*\) which minimizes the cost function.
Then \(y(x,\theta^*)\) is the desired prediction model.
(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()

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)\).
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}\):
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)
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
to create variational quantum circuit \(U(\theta)\):
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:
[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>]

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()

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
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()

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

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.
load(self: qulacs_core.DensityMatrix, state: qulacs_core.QuantumStateBase) -> None
Load quantum state vector or density matrix
load(self: qulacs_core.DensityMatrix, state: List[complex]) -> None
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.
sampling(self: qulacs_core.DensityMatrix, sampling_count: int) -> List[int]
Sampling measurement results
sampling(self: qulacs_core.DensityMatrix, sampling_count: int, random_seed: int) -> List[int]
- set_Haar_random_state(*args, **kwargs)¶
Overloaded function.
set_Haar_random_state(self: qulacs_core.DensityMatrix) -> None
Set Haar random state
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_string(self: qulacs_core.DensityMatrix) str ¶
to string
- class qulacs_core.GeneralQuantumOperator¶
Bases:
pybind11_builtins.pybind11_object
- add_operator(*args, **kwargs)¶
Overloaded function.
add_operator(self: qulacs_core.GeneralQuantumOperator, pauli_operator: qulacs_core.PauliOperator) -> None
Add Pauli operator
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.
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.
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_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
- class qulacs_core.GradCalculator¶
Bases:
pybind11_builtins.pybind11_object
- calculate_grad(*args, **kwargs)¶
Overloaded function.
calculate_grad(self: qulacs_core.GradCalculator, parametric_circuit: qulacs_core.ParametricQuantumCircuit, observable: qulacs_core.Observable) -> List[complex]
Calculate Grad
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.
add_operator(self: qulacs_core.Observable, pauli_operator: qulacs_core.PauliOperator) -> None
Add Pauli operator
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.
add_random_operator(self: qulacs_core.Observable, operator_count: int) -> None
Add random pauli operator
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_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.
add_gate(self: qulacs_core.ParametricQuantumCircuit, gate: qulacs_core.QuantumGateBase) -> None
Add gate
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.
add_parametric_gate(self: qulacs_core.ParametricQuantumCircuit, gate: qulacs_core.QuantumGate_SingleParameter) -> None
Add parametric gate
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.
add_dense_matrix_gate(self: qulacs_core.QuantumCircuit, index: int, matrix: numpy.ndarray[numpy.complex128[m, n]]) -> None
Add dense matrix gate
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.
add_gate(self: qulacs_core.QuantumCircuit, gate: qulacs_core.QuantumGateBase) -> None
Add gate with copy
add_gate(self: qulacs_core.QuantumCircuit, gate: qulacs_core.QuantumGateBase, position: int) -> None
- add_multi_Pauli_gate(*args, **kwargs)¶
Overloaded function.
add_multi_Pauli_gate(self: qulacs_core.QuantumCircuit, index_list: List[int], pauli_ids: List[int]) -> None
Add multi-qubit Pauli gate
add_multi_Pauli_gate(self: qulacs_core.QuantumCircuit, pauli: qulacs_core.PauliOperator) -> None
- add_multi_Pauli_rotation_gate(*args, **kwargs)¶
Overloaded function.
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
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.
add_random_unitary_gate(self: qulacs_core.QuantumCircuit, index_list: List[int]) -> None
Add random unitary gate
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_string(self: qulacs_core.QuantumCircuit) str ¶
Get string representation
- update_quantum_state(*args, **kwargs)¶
Overloaded function.
update_quantum_state(self: qulacs_core.QuantumCircuit, state: qulacs_core.QuantumStateBase) -> None
Update quantum state
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.
initialize_random_state(self: qulacs_core.QuantumCircuitSimulator) -> None
Initialize state with random pure state
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_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
- class qulacs_core.QuantumGate_CPTP¶
Bases:
qulacs_core.QuantumGateBase
QuantumGate_Instrument
- 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.
load(self: qulacs_core.QuantumState, state: qulacs_core.QuantumStateBase) -> None
Load quantum state vector
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.
sampling(self: qulacs_core.QuantumState, sampling_count: int) -> List[int]
Sampling measurement results
sampling(self: qulacs_core.QuantumState, sampling_count: int, random_seed: int) -> List[int]
- set_Haar_random_state(*args, **kwargs)¶
Overloaded function.
set_Haar_random_state(self: qulacs_core.QuantumState) -> None
Set Haar random state
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_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.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.
partial_trace(state: qulacs_core.QuantumState, target_traceout: List[int]) -> qulacs_core.DensityMatrix
Take partial trace
partial_trace(state: qulacs_core.DensityMatrix, target_traceout: List[int]) -> qulacs_core.DensityMatrix
- qulacs_core.state.permutate_qubit(*args, **kwargs)¶
Overloaded function.
permutate_qubit(state: qulacs_core.QuantumState, qubit_order: List[int]) -> qulacs_core.QuantumState
Permutate qubits from state
permutate_qubit(state: qulacs_core.DensityMatrix, qubit_order: List[int]) -> qulacs_core.DensityMatrix
- qulacs_core.state.tensor_product(*args, **kwargs)¶
Overloaded function.
tensor_product(state_left: qulacs_core.QuantumState, state_right: qulacs_core.QuantumState) -> qulacs_core.QuantumState
Get tensor product of states
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.
Adaptive(gate: qulacs_core.QuantumGateBase, condition: Callable[[List[int]], bool]) -> qulacs_core.QuantumGateBase
Create adaptive gate
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.
DenseMatrix(index: int, matrix: numpy.ndarray[numpy.complex128[m, n]]) -> qulacs_core.QuantumGateMatrix
Create dense matrix gate
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.
RandomUnitary(index_list: List[int]) -> qulacs_core.QuantumGateMatrix
Create random unitary gate
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.
add(gate1: qulacs_core.QuantumGateBase, gate2: qulacs_core.QuantumGateBase) -> qulacs_core.QuantumGateMatrix
Add quantum gate matrices
add(gate_list: List[qulacs_core.QuantumGateBase]) -> qulacs_core.QuantumGateMatrix
Add quantum gate matrices
- qulacs_core.gate.merge(*args, **kwargs)¶
Overloaded function.
merge(gate1: qulacs_core.QuantumGateBase, gate2: qulacs_core.QuantumGateBase) -> qulacs_core.QuantumGateMatrix
Merge two quantum gate or gate list
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.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.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
C++ API Reference¶
Class Hierarchy¶
-
- Class AdamOptimizer
- Class BooleanFormula
- Class BooleanOptimizationProblem
- Class CausalConeSimulator
- Class ClassificationProblem
- Class ClsNoisyEvolution
- Class ClsNoisyEvolution_auto
- Class ClsNoisyEvolution_fast
- Class ClsOneControlOneTargetGate
- Class ClsOneQubitGate
- Class ClsOneQubitRotationGate
- Class ClsParametricPauliRotationGate
- Class ClsParametricRXGate
- Class ClsParametricRYGate
- Class ClsParametricRZGate
- Class ClsPauliGate
- Class ClsPauliRotationGate
- Class ClsReversibleBooleanGate
- Class ClsStateReflectionGate
- Class ClsTwoQubitGate
- Class ControlQubitInfo
- Class DensityMatrixCpu
- Class DiagonalizationEnergyMinimizationSolver
- Class DuplicatedQubitIndexException
- Class EnergyMinimizationProblem
- Class GateIndexOutOfRangeException
- Class GeneralQuantumOperator
- Class GradCalculator
- Class GradientBasedOptimizer
- Class GradientByHalfPi
- Class GradientDecentOptimizer
- Class GradientFreeOptimizer
- Class HermitianQuantumOperator
- Class InvalidControlQubitException
- Class InvalidMatrixGateSizeException
- Class InvalidNoiseTypeIdentifierException
- Class InvalidObservableException
- Class InvalidOpenfermionFormatException
- Class InvalidPauliIdentifierException
- Class InvalidProbabilityDistributionException
- Class InvalidQuantumOperatorException
- Class InvalidQubitCountException
- Class InvalidStateVectorSizeException
- Class IOException
- Class KAK_data
- Class MatrixIndexOutOfRangeException
- Class NoiseSimulator
- Struct NoiseSimulator::Result
- Struct NoiseSimulator::SamplingRequest
- Class NonHermitianException
- Class NotImplementedException
- Class OperatorIndexOutOfRangeException
- Class Optimizer
- Class ParameterIndexOutOfRangeException
- Class ParametricCircuitBuilder
- Class ParametricQuantumCircuit
- Class ParametricQuantumCircuitSimulator
- Class PauliOperator
- Class QuantumCircuit
- Class QuantumCircuitBuilder
- Class QuantumCircuitEnergyMinimizationSolver
- Class QuantumCircuitGradientDifferentiation
- Class QuantumCircuitOptimizer
- Class QuantumCircuitSimulator
- Class QuantumGate_Adaptive
- Class QuantumGate_CP
- Class QuantumGate_CPTP
- Class QuantumGate_Probabilistic
- Class QuantumGate_SingleParameter
- Class QuantumGate_SingleParameterOneQubitRotation
- Class QuantumGateBase
- Class QuantumGateDiagonalMatrix
- Class QuantumGateMatrix
- Class QuantumGateSparseMatrix
- Class QuantumStateBase
- Class QuantumStateCpu
- Class QuantumStateProcessorException
- Class QubitIndexOutOfRangeException
- Class QubitInfo
- Class Random
- Class RegressionProblem
- Class SinglePauliOperator
- Class TargetQubitInfo
- Class Timer
- Class UndefinedUpdateFuncException
- Class UnionFind
File Hierarchy¶
-
- Directory src
- Directory cppsim
- File circuit.hpp
- File circuit_builder.hpp
- File circuit_optimizer.hpp
- File exception.hpp
- File gate.hpp
- File gate_factory.hpp
- File gate_general.hpp
- File gate_matrix.hpp
- File gate_matrix_diagonal.hpp
- File gate_matrix_sparse.hpp
- File gate_merge.hpp
- File gate_named_one.hpp
- File gate_named_pauli.hpp
- File gate_named_two.hpp
- File gate_noisy_evolution.hpp
- File gate_reflect.hpp
- File gate_reversible.hpp
- File gate_to_gqo.hpp
- File general_quantum_operator.hpp
- File matrix_decomposition.hpp
- File noisesimulator.hpp
- File observable.hpp
- File pauli_operator.hpp
- File qubit_info.hpp
- File simulator.hpp
- File state.hpp
- File state_dm.hpp
- File state_gpu.hpp
- File type.hpp
- File utility.hpp
- Directory vqcsim
- File boolean_formula.hpp
- File causalcone_simulator.hpp
- File differential.hpp
- File GradCalculator.hpp
- File loss_function.hpp
- File optimizer.hpp
- File parametric_circuit.hpp
- File parametric_circuit_builder.hpp
- File parametric_gate.hpp
- File parametric_gate_factory.hpp
- File parametric_simulator.hpp
- File parser.hpp
- File problem.hpp
- File solver.hpp
- Directory cppsim
- Directory src
Full API¶
Namespaces¶
Namespace gate¶
Contents
Namespace state¶
Contents
Function state::partial_trace(const QuantumStateCpu *, std::vector<UINT>)
Function state::partial_trace(const DensityMatrixCpu *, std::vector<UINT>)
Function state::permutate_qubit(const DensityMatrixCpu *, std::vector<UINT>)
Function state::permutate_qubit(const QuantumState *, std::vector<UINT>)
Function state::tensor_product(const QuantumState *, const QuantumState *)
Function state::tensor_product(const DensityMatrixCpu *, const DensityMatrixCpu *)
Classes and Structs¶
Struct NoiseSimulator::Result¶
Defined in File noisesimulator.hpp
This struct is a nested type of Class NoiseSimulator.
-
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
-
Result(const std::vector<std::pair<QuantumState*, UINT>> &result_)
Struct NoiseSimulator::SamplingRequest¶
Defined in File noisesimulator.hpp
This struct is a nested type of Class NoiseSimulator.
-
struct NoiseSimulator::SamplingRequest¶
Public Functions
-
inline SamplingRequest(std::vector<UINT> init_gate_pos, UINT init_num_of_sampling)¶
-
inline SamplingRequest(std::vector<UINT> init_gate_pos, UINT init_num_of_sampling)¶
Class AdamOptimizer¶
Defined in File optimizer.hpp
public GradientBasedOptimizer
(Class GradientBasedOptimizer)
-
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¶
-
inline AdamOptimizer(UINT trainable_parameter_count, double learning_rate = 0.001, double beta1 = 0.9, double beta2 = 0.999, double epsilon = 1e-8)¶
Class BooleanFormula¶
Defined in File boolean_formula.hpp
-
class BooleanFormula¶
Class BooleanOptimizationProblem¶
Defined in File problem.hpp
-
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¶
-
inline BooleanOptimizationProblem(BooleanFormula *boolean_formula)¶
Class CausalConeSimulator¶
Defined in File causalcone_simulator.hpp
-
class CausalConeSimulator¶
Public Functions
-
inline CausalConeSimulator(const ParametricQuantumCircuit &_init_circuit, const Observable &_init_observable)¶
-
inline ~CausalConeSimulator()¶
-
inline void build()¶
-
inline std::vector<std::vector<ParametricQuantumCircuit*>> get_circuit_list()¶
-
inline std::vector<std::vector<PauliOperator>> get_pauli_operator_list()¶
Public Members
-
ParametricQuantumCircuit *init_circuit¶
-
Observable *init_observable¶
-
std::vector<std::vector<ParametricQuantumCircuit*>> circuit_list¶
-
std::vector<std::vector<PauliOperator>> pauli_operator_list¶
-
bool build_run = false¶
-
inline CausalConeSimulator(const ParametricQuantumCircuit &_init_circuit, const Observable &_init_observable)¶
Class ClassificationProblem¶
Defined in File problem.hpp
-
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¶
-
inline ClassificationProblem(std::vector<std::vector<double>> input_data, std::vector<UINT> label_data)¶
Class ClsNoisyEvolution¶
Defined in File gate_noisy_evolution.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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¶
-
ClsNoisyEvolution(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time, double dt = 1e-6)¶
Class ClsNoisyEvolution_auto¶
Defined in File gate_noisy_evolution.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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¶
-
inline ClsNoisyEvolution_auto()¶
Class ClsNoisyEvolution_fast¶
Defined in File gate_noisy_evolution.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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¶
-
ClsNoisyEvolution_fast(Observable *hamiltonian, std::vector<GeneralQuantumOperator*> c_ops, double time)¶
Class ClsOneControlOneTargetGate¶
Defined in File gate_named_two.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 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¶
-
inline explicit ClsOneControlOneTargetGate()¶
Class ClsOneQubitGate¶
Defined in File gate_named_one.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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)¶
-
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¶
-
inline explicit ClsOneQubitGate()¶
Class ClsOneQubitRotationGate¶
Defined in File gate_named_one.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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)¶
-
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¶
-
inline explicit ClsOneQubitRotationGate()¶
Class ClsParametricPauliRotationGate¶
Defined in File parametric_gate.hpp
public QuantumGate_SingleParameter
(Class QuantumGate_SingleParameter)
-
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 ClsParametricPauliRotationGate *get_inverse() const override¶
Protected Attributes
-
PauliOperator *_pauli¶
-
inline ClsParametricPauliRotationGate(double angle, PauliOperator *pauli)¶
Class ClsParametricRXGate¶
Defined in File parametric_gate.hpp
public QuantumGate_SingleParameterOneQubitRotation
(Class QuantumGate_SingleParameterOneQubitRotation)
-
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 ClsParametricRXGate *get_inverse() const override¶
-
inline ClsParametricRXGate(UINT target_qubit_index, double angle)¶
Class ClsParametricRYGate¶
Defined in File parametric_gate.hpp
public QuantumGate_SingleParameterOneQubitRotation
(Class QuantumGate_SingleParameterOneQubitRotation)
-
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 ClsParametricRYGate *get_inverse() const override¶
-
inline ClsParametricRYGate(UINT target_qubit_index, double angle)¶
Class ClsParametricRZGate¶
Defined in File parametric_gate.hpp
public QuantumGate_SingleParameterOneQubitRotation
(Class QuantumGate_SingleParameterOneQubitRotation)
-
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 ClsParametricRZGate *get_inverse() const override¶
-
inline ClsParametricRZGate(UINT target_qubit_index, double angle)¶
Class ClsPauliGate¶
Defined in File gate_named_pauli.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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¶
Protected Attributes
-
PauliOperator *_pauli¶
-
inline explicit ClsPauliGate(PauliOperator *pauli)¶
Class ClsPauliRotationGate¶
Defined in File gate_named_pauli.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 ClsPauliRotationGate *get_inverse(void) const override¶
-
inline ClsPauliRotationGate(double angle, PauliOperator *pauli)¶
Class ClsReversibleBooleanGate¶
Defined in File gate_reversible.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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¶
-
inline ClsReversibleBooleanGate(std::vector<UINT> target_qubit_index_list, std::function<ITYPE(ITYPE, ITYPE)> _function_ptr)¶
Class ClsStateReflectionGate¶
Defined in File gate_reflect.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 explicit ClsStateReflectionGate(const QuantumState *_reflection_state)¶
Class ClsTwoQubitGate¶
Defined in File gate_named_two.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 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¶
-
inline explicit ClsTwoQubitGate()¶
Class ControlQubitInfo¶
Defined in File qubit_info.hpp
public QubitInfo
(Class QubitInfo)
-
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¶
-
inline UINT control_value() const¶
Class DensityMatrixCpu¶
Defined in File state_dm.hpp
public QuantumStateBase
(Class QuantumStateBase)
-
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 Eigen::VectorXcd &_state)¶
-
inline virtual void load(const ComplexMatrix &_state)¶
-
inline virtual const std::string get_device_name() const override¶
-
inline virtual void *data() const override¶
-
inline virtual CTYPE *data_c() const override¶
-
inline virtual CTYPE *duplicate_data_c() 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 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 explicit DensityMatrixCpu(UINT qubit_count_)¶
Class DiagonalizationEnergyMinimizationSolver¶
Defined in File solver.hpp
Class DuplicatedQubitIndexException¶
Defined in File exception.hpp
public logic_error
Class EnergyMinimizationProblem¶
Defined in File problem.hpp
-
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¶
-
inline EnergyMinimizationProblem(Observable *observable)¶
Class GateIndexOutOfRangeException¶
Defined in File exception.hpp
public out_of_range
Class GeneralQuantumOperator¶
Defined in File general_quantum_operator.hpp
public HermitianQuantumOperator
(Class HermitianQuantumOperator)
-
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 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¶
-
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¶
-
explicit GeneralQuantumOperator(const UINT qubit_count)¶
Class GradCalculator¶
Defined in File GradCalculator.hpp
-
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)¶
-
std::vector<std::complex<double>> calculate_grad(ParametricQuantumCircuit &x, Observable &obs, std::vector<double> theta)¶
Class GradientBasedOptimizer¶
Defined in File optimizer.hpp
public Optimizer
(Class Optimizer)
public AdamOptimizer
(Class AdamOptimizer)public GradientDecentOptimizer
(Class GradientDecentOptimizer)
-
class GradientBasedOptimizer : public Optimizer¶
Subclassed by AdamOptimizer, GradientDecentOptimizer
Class GradientByHalfPi¶
Defined in File differential.hpp
public QuantumCircuitGradientDifferentiation
(Class QuantumCircuitGradientDifferentiation)
-
class GradientByHalfPi : public QuantumCircuitGradientDifferentiation¶
Public Functions
-
virtual double compute_gradient(ParametricQuantumCircuitSimulator *sim, const EnergyMinimizationProblem *instance, const std::vector<double> ¶meter, std::vector<double> *gradient) override¶
-
virtual double compute_gradient(ParametricQuantumCircuitSimulator *sim, const EnergyMinimizationProblem *instance, const std::vector<double> ¶meter, std::vector<double> *gradient) override¶
Class GradientDecentOptimizer¶
Defined in File optimizer.hpp
public GradientBasedOptimizer
(Class GradientBasedOptimizer)
-
class GradientDecentOptimizer : public GradientBasedOptimizer¶
Class GradientFreeOptimizer¶
Defined in File optimizer.hpp
public Optimizer
(Class Optimizer)
Class HermitianQuantumOperator¶
Defined in File observable.hpp
public GeneralQuantumOperator
(Class GeneralQuantumOperator)
-
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 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¶
-
virtual void add_operator(const PauliOperator *mpt) override¶
Class InvalidControlQubitException¶
Defined in File exception.hpp
public logic_error
Class InvalidMatrixGateSizeException¶
Defined in File exception.hpp
public logic_error
Class InvalidNoiseTypeIdentifierException¶
Defined in File exception.hpp
public domain_error
Class InvalidObservableException¶
Defined in File exception.hpp
public logic_error
Class InvalidOpenfermionFormatException¶
Defined in File exception.hpp
public logic_error
Class InvalidPauliIdentifierException¶
Defined in File exception.hpp
public domain_error
Class InvalidProbabilityDistributionException¶
Defined in File exception.hpp
public logic_error
Class InvalidQuantumOperatorException¶
Defined in File exception.hpp
public logic_error
Class InvalidQubitCountException¶
Defined in File exception.hpp
public logic_error
Class InvalidStateVectorSizeException¶
Defined in File exception.hpp
public logic_error
Class IOException¶
Defined in File exception.hpp
public runtime_error
Class KAK_data¶
Defined in File matrix_decomposition.hpp
-
class KAK_data¶
Public Members
-
QuantumGateMatrix *single_qubit_operations_before[2]¶
-
double interaction_coefficients[3]¶
-
QuantumGateMatrix *single_qubit_operations_after[2]¶
-
QuantumGateMatrix *single_qubit_operations_before[2]¶
Class MatrixIndexOutOfRangeException¶
Defined in File exception.hpp
public out_of_range
Class NoiseSimulator¶
Defined in File noisesimulator.hpp
-
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)¶
-
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¶
-
Result(const std::vector<std::pair<QuantumState*, UINT>> &result_)¶
-
explicit NoiseSimulator(const QuantumCircuit *init_circuit, const QuantumState *init_state = NULL)¶
Class NonHermitianException¶
Defined in File exception.hpp
public logic_error
Class NotImplementedException¶
Defined in File exception.hpp
public logic_error
Class OperatorIndexOutOfRangeException¶
Defined in File exception.hpp
public out_of_range
Class Optimizer¶
Defined in File optimizer.hpp
public GradientBasedOptimizer
(Class GradientBasedOptimizer)public GradientFreeOptimizer
(Class GradientFreeOptimizer)
-
class Optimizer¶
Subclassed by GradientBasedOptimizer, GradientFreeOptimizer
Protected Attributes
-
UINT _trainable_parameter_count¶
-
UINT _trainable_parameter_count¶
Class ParameterIndexOutOfRangeException¶
Defined in File exception.hpp
public out_of_range
Class ParametricCircuitBuilder¶
Defined in File parametric_circuit_builder.hpp
public QuantumCircuitBuilder
(Class QuantumCircuitBuilder)
-
class ParametricCircuitBuilder : public QuantumCircuitBuilder¶
Class ParametricQuantumCircuit¶
Defined in File parametric_circuit.hpp
public QuantumCircuit
(Class QuantumCircuit)
-
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)¶
Friends
-
friend std::ostream &operator<<(std::ostream &os, const ParametricQuantumCircuit&)¶
-
friend std::ostream &operator<<(std::ostream &os, const ParametricQuantumCircuit *circuit)¶
-
ParametricQuantumCircuit(UINT qubit_count)¶
Class ParametricQuantumCircuitSimulator¶
Defined in File parametric_simulator.hpp
public QuantumCircuitSimulator
(Class QuantumCircuitSimulator)
-
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)¶
-
ParametricQuantumCircuitSimulator(ParametricQuantumCircuit *circuit, QuantumStateBase *state = NULL)¶
Class PauliOperator¶
Defined in File pauli_operator.hpp
-
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¶
-
PauliOperator(const std::vector<UINT> &target_qubit_index_list, std::string Pauli_operator_type_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 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 std::string get_pauli_string() const¶
-
PauliOperator operator*(const PauliOperator &target) const¶
-
PauliOperator operator*(CPPCTYPE target) const¶
-
PauliOperator &operator*=(const PauliOperator &target)¶
-
PauliOperator &operator*=(CPPCTYPE target)¶
-
inline std::vector<UINT> get_index_list() const¶
Class QuantumCircuit¶
Defined in File circuit.hpp
public ParametricQuantumCircuit
(Class ParametricQuantumCircuit)
-
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 QuantumCircuit *get_inverse(void)¶
Protected Functions
-
QuantumCircuit(const QuantumCircuit &obj)¶
-
QuantumCircuit &operator=(const QuantumCircuit&) = delete¶
Friends
-
friend std::ostream &operator<<(std::ostream &os, const QuantumCircuit&)¶
-
friend std::ostream &operator<<(std::ostream &os, const QuantumCircuit *gate)¶
-
explicit QuantumCircuit(UINT qubit_count)¶
Class QuantumCircuitBuilder¶
Defined in File circuit_builder.hpp
public ParametricCircuitBuilder
(Class ParametricCircuitBuilder)
-
class QuantumCircuitBuilder¶
Subclassed by ParametricCircuitBuilder
Public Functions
-
virtual QuantumCircuit *create_circuit(UINT qubit_count) const = 0¶
-
virtual QuantumCircuit *create_circuit(UINT qubit_count) const = 0¶
Class QuantumCircuitEnergyMinimizationSolver¶
Defined in File solver.hpp
-
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¶
-
inline QuantumCircuitEnergyMinimizationSolver(const std::function<ParametricQuantumCircuit*(UINT, UINT)> *circuit_generator, UINT param_count = 0)¶
Class QuantumCircuitGradientDifferentiation¶
Defined in File differential.hpp
public GradientByHalfPi
(Class GradientByHalfPi)
-
class QuantumCircuitGradientDifferentiation¶
Subclassed by GradientByHalfPi
Public Functions
-
virtual double compute_gradient(ParametricQuantumCircuitSimulator *sim, const EnergyMinimizationProblem *instance, const std::vector<double> ¶meter, std::vector<double> *gradient) = 0¶
-
virtual double compute_gradient(ParametricQuantumCircuitSimulator *sim, const EnergyMinimizationProblem *instance, const std::vector<double> ¶meter, std::vector<double> *gradient) = 0¶
Class QuantumCircuitOptimizer¶
Defined in File circuit_optimizer.hpp
-
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)¶
-
inline QuantumCircuitOptimizer()¶
Class QuantumCircuitSimulator¶
Defined in File simulator.hpp
public ParametricQuantumCircuitSimulator
(Class ParametricQuantumCircuitSimulator)
-
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¶
-
explicit QuantumCircuitSimulator(QuantumCircuit *circuit, QuantumStateBase *initial_state = NULL)¶
Class QuantumGate_Adaptive¶
Defined in File gate_general.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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¶
-
inline explicit QuantumGate_Adaptive(QuantumGateBase *gate, std::function<bool(const std::vector<UINT>&)> func_without_id)¶
Class QuantumGate_CP¶
Defined in File gate_general.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 explicit QuantumGate_CP(std::vector<QuantumGateBase*> gate_list, bool state_normalize, bool probability_normalize, bool assign_zero_if_not_matched)¶
Class QuantumGate_CPTP¶
Defined in File gate_general.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 explicit QuantumGate_CPTP(std::vector<QuantumGateBase*> gate_list)¶
Class QuantumGate_Probabilistic¶
Defined in File gate_general.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 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¶
-
inline explicit QuantumGate_Probabilistic(const std::vector<double> &distribution, const std::vector<QuantumGateBase*> &gate_list)¶
Class QuantumGate_SingleParameter¶
Defined in File parametric_gate.hpp
public QuantumGateBase
(Class QuantumGateBase)
public ClsParametricPauliRotationGate
(Class ClsParametricPauliRotationGate)public QuantumGate_SingleParameterOneQubitRotation
(Class QuantumGate_SingleParameterOneQubitRotation)
-
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¶
-
inline QuantumGate_SingleParameter(double angle)¶
Class QuantumGate_SingleParameterOneQubitRotation¶
Defined in File parametric_gate.hpp
public QuantumGate_SingleParameter
(Class QuantumGate_SingleParameter)
public ClsParametricRXGate
(Class ClsParametricRXGate)public ClsParametricRYGate
(Class ClsParametricRYGate)public ClsParametricRZGate
(Class ClsParametricRZGate)
-
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¶
-
inline virtual void update_quantum_state(QuantumStateBase *state) override¶
Class QuantumGateBase¶
Defined in File gate.hpp
public ClsNoisyEvolution
(Class ClsNoisyEvolution)public ClsNoisyEvolution_auto
(Class ClsNoisyEvolution_auto)public ClsNoisyEvolution_fast
(Class ClsNoisyEvolution_fast)public ClsOneControlOneTargetGate
(Class ClsOneControlOneTargetGate)public ClsOneQubitGate
(Class ClsOneQubitGate)public ClsOneQubitRotationGate
(Class ClsOneQubitRotationGate)public ClsPauliGate
(Class ClsPauliGate)public ClsPauliRotationGate
(Class ClsPauliRotationGate)public ClsReversibleBooleanGate
(Class ClsReversibleBooleanGate)public ClsStateReflectionGate
(Class ClsStateReflectionGate)public ClsTwoQubitGate
(Class ClsTwoQubitGate)public QuantumGate_Adaptive
(Class QuantumGate_Adaptive)public QuantumGate_CP
(Class QuantumGate_CP)public QuantumGate_CPTP
(Class QuantumGate_CPTP)public QuantumGate_Probabilistic
(Class QuantumGate_Probabilistic)public QuantumGate_SingleParameter
(Class QuantumGate_SingleParameter)public QuantumGateDiagonalMatrix
(Class QuantumGateDiagonalMatrix)public QuantumGateMatrix
(Class QuantumGateMatrix)public QuantumGateSparseMatrix
(Class QuantumGateSparseMatrix)
-
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¶
-
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)¶
-
inline virtual ~QuantumGateBase()¶
Class QuantumGateDiagonalMatrix¶
Defined in File gate_matrix_diagonal.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 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¶
Friends
-
friend std::ostream &operator<<(std::ostream &os, const QuantumGateDiagonalMatrix &gate)¶
-
friend std::ostream &operator<<(std::ostream &os, QuantumGateDiagonalMatrix *gate)¶
-
QuantumGateDiagonalMatrix(const std::vector<UINT> &target_qubit_index_list, const ComplexVector &matrix_element, const std::vector<UINT> &control_qubit_index_list = {})¶
Class QuantumGateMatrix¶
Defined in File gate_matrix.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 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 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)¶
-
QuantumGateMatrix(const std::vector<UINT> &target_qubit_index_list, const ComplexMatrix &matrix_element, const std::vector<UINT> &control_qubit_index_list = {})¶
Class QuantumGateSparseMatrix¶
Defined in File gate_matrix_sparse.hpp
public QuantumGateBase
(Class QuantumGateBase)
-
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 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¶
Friends
-
friend std::ostream &operator<<(std::ostream &os, const QuantumGateSparseMatrix &gate)¶
-
friend std::ostream &operator<<(std::ostream &os, QuantumGateSparseMatrix *gate)¶
-
QuantumGateSparseMatrix(const std::vector<UINT> &target_qubit_index_list, const SparseComplexMatrix &matrix_element, const std::vector<UINT> &control_qubit_index_list = {})¶
Class QuantumStateBase¶
Defined in File state.hpp
public DensityMatrixCpu
(Class DensityMatrixCpu)public QuantumStateCpu
(Class QuantumStateCpu)
-
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 const std::string get_device_name() const = 0¶
-
virtual void *data() const = 0¶
-
virtual CTYPE *data_c() 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¶
-
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¶
-
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)¶
-
inline QuantumStateBase(UINT qubit_count_, bool is_state_vector)¶
Class QuantumStateCpu¶
Defined in File state.hpp
public QuantumStateBase
(Class QuantumStateBase)
-
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 const std::string get_device_name() const override¶
-
inline virtual void *data() const override¶
-
inline virtual CTYPE *data_c() const override¶
-
inline virtual CTYPE *duplicate_data_c() 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_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 explicit QuantumStateCpu(UINT qubit_count_)¶
Class QuantumStateProcessorException¶
Defined in File exception.hpp
public logic_error
Class QubitIndexOutOfRangeException¶
Defined in File exception.hpp
public out_of_range
Class QubitInfo¶
Defined in File qubit_info.hpp
public ControlQubitInfo
(Class ControlQubitInfo)public TargetQubitInfo
(Class TargetQubitInfo)
-
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¶
-
inline virtual ~QubitInfo()¶
Class Random¶
Defined in File utility.hpp
-
class Random¶
Class RegressionProblem¶
Defined in File problem.hpp
-
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¶
-
inline RegressionProblem(std::vector<std::vector<double>> input_data, std::vector<std::vector<double>> output_data)¶
Class SinglePauliOperator¶
Defined in File pauli_operator.hpp
Class TargetQubitInfo¶
Defined in File qubit_info.hpp
public QubitInfo
(Class QubitInfo)
-
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¶
-
inline TargetQubitInfo(void)¶
Class Timer¶
Defined in File utility.hpp
-
class Timer¶
Class UndefinedUpdateFuncException¶
Defined in File exception.hpp
public logic_error
Functions¶
Function bidiagonalize_real_matrix_pair_with_symmetric_products¶
Defined in File matrix_decomposition.hpp
-
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¶
Defined in File matrix_decomposition.hpp
-
std::tuple<Eigen::Matrix4cd, Eigen::Matrix4cd, Eigen::Matrix4cd> bidiagonalize_unitary_with_special_orthogonals(Eigen::Matrix4cd mat)¶
Function check_is_unique_index_list¶
Defined in File utility.hpp
-
bool check_is_unique_index_list(const std::vector<UINT> &index_list)¶
Function check_Pauli_operator¶
Defined in File general_quantum_operator.hpp
-
bool check_Pauli_operator(const GeneralQuantumOperator *quantum_operator, const PauliOperator *pauli_operator)¶
Function chfmt¶
Defined in File utility.hpp
-
void chfmt(std::string &ops)¶
Function convert_observable_to_matrix¶
Defined in File observable.hpp
-
ComplexMatrix convert_observable_to_matrix(const HermitianQuantumOperator &observable)¶
Function count_population_cpp¶
Defined in File utility.hpp
-
static inline UINT count_population_cpp(ITYPE x)¶
Function CSD¶
Defined in File matrix_decomposition.hpp
-
std::vector<QuantumGateBase*> CSD(QuantumGateBase *target_gate)¶
Function CSD_internal¶
Defined in File matrix_decomposition.hpp
-
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>&)>)¶
Defined in File gate_merge.hpp
-
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)¶
Defined in File gate_merge.hpp
-
QuantumGateBase *gate::Adaptive(QuantumGateBase *gate, std::function<bool(const std::vector<UINT>&, UINT)> func, UINT id)¶
Function gate::add(const QuantumGateBase *, const QuantumGateBase *)¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::add(const QuantumGateBase *gate1, const QuantumGateBase *gate2)¶
Function gate::add(std::vector<QuantumGateBase *>)¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::add(std::vector<QuantumGateBase*> gate_list)¶
Function gate::AmplitudeDampingNoise¶
Defined in File gate_factory.hpp
-
QuantumGate_CPTP *gate::AmplitudeDampingNoise(UINT target_index, double prob)¶
Amplitude damping noiseを発生させるゲート
- Parameters
target_index – [in] ターゲットとなる量子ビットの添え字
prob – [in] エラーが生じる確率
- Returns
作成されたゲートのインスタンス
Function gate::BitFlipNoise¶
Defined in File gate_factory.hpp
-
QuantumGate_Probabilistic *gate::BitFlipNoise(UINT target_index, double prob)¶
bit-flipノイズを発生させるゲート
- Parameters
target_index – [in] ターゲットとなる量子ビットの添え字
prob – [in] エラーが生じる確率
- Returns
作成されたゲートのインスタンス
Function gate::CNOT¶
Defined in File gate_factory.hpp
-
ClsOneControlOneTargetGate *gate::CNOT(UINT control_qubit_index, UINT target_qubit_index)¶
Function gate::CP¶
Defined in File gate_merge.hpp
-
QuantumGateBase *gate::CP(std::vector<QuantumGateBase*> gate_list, bool state_normalize, bool probability_normalize, bool assign_zero_if_not_matched)¶
Function gate::CPTP¶
Defined in File gate_merge.hpp
-
QuantumGateBase *gate::CPTP(std::vector<QuantumGateBase*> gate_list)¶
Function gate::create_parametric_quantum_gate_from_string¶
Defined in File parametric_gate_factory.hpp
-
QuantumGateBase *gate::create_parametric_quantum_gate_from_string(std::string gate_string)¶
Function gate::create_quantum_gate_from_string¶
Defined in File gate_factory.hpp
-
QuantumGateBase *gate::create_quantum_gate_from_string(std::string gate_string)¶
Function gate::CZ¶
Defined in File gate_factory.hpp
-
ClsOneControlOneTargetGate *gate::CZ(UINT control_qubit_index, UINT target_qubit_index)¶
Function gate::DenseMatrix(UINT, ComplexMatrix)¶
Defined in File gate_factory.hpp
-
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)¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
QuantumGate_Probabilistic *gate::DephasingNoise(UINT target_index, double prob)¶
phase-flipノイズを発生させるゲート
- Parameters
target_index – [in] ターゲットとなる量子ビットの添え字
prob – [in] エラーが生じる確率
- Returns
作成されたゲートのインスタンス
Function gate::DepolarizingNoise¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
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::get_adjoint_gate¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::get_adjoint_gate(const QuantumGateBase *gate)¶
Function gate::get_conjugate_gate¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::get_conjugate_gate(const QuantumGateBase *gate)¶
Function gate::get_extended_matrix¶
Defined in File gate_merge.hpp
-
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¶
Defined in File gate_merge.hpp
-
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¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::get_transpose_gate(const QuantumGateBase *gate)¶
Function gate::H¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::H(UINT qubit_index)¶
Function gate::Identity¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::Identity(UINT qubit_index)¶
Function gate::IndependentXZNoise¶
Defined in File gate_factory.hpp
-
QuantumGate_Probabilistic *gate::IndependentXZNoise(UINT target_index, double prob)¶
bit-flipとphase-flipを同じ確率でノイズを発生させるゲート
- Parameters
target_index – [in] ターゲットとなる量子ビットの添え字
prob – [in] エラーが生じる確率
- Returns
作成されたゲートのインスタンス
Function gate::Instrument¶
Defined in File gate_merge.hpp
-
QuantumGateBase *gate::Instrument(std::vector<QuantumGateBase*> gate_list, UINT classical_register_address)¶
Function gate::Measurement¶
Defined in File gate_factory.hpp
-
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 *)¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::merge(const QuantumGateBase *gate_applied_first, const QuantumGateBase *gate_applied_later)¶
Function gate::merge(std::vector<QuantumGateBase *>)¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::merge(std::vector<QuantumGateBase*> gate_list)¶
Function gate::NoisyEvolution¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::P0(UINT qubit_index)¶
Function gate::P1¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::P1(UINT qubit_index)¶
Function gate::ParametricPauliRotation¶
Defined in File parametric_gate_factory.hpp
-
QuantumGate_SingleParameter *gate::ParametricPauliRotation(std::vector<UINT> target, std::vector<UINT> pauli_id, double initial_angle = 0.)¶
Function gate::ParametricRX¶
Defined in File parametric_gate_factory.hpp
-
QuantumGate_SingleParameter *gate::ParametricRX(UINT qubit_index, double initial_angle = 0.)¶
Function gate::ParametricRY¶
Defined in File parametric_gate_factory.hpp
-
QuantumGate_SingleParameter *gate::ParametricRY(UINT qubit_index, double initial_angle = 0.)¶
Function gate::ParametricRZ¶
Defined in File parametric_gate_factory.hpp
-
QuantumGate_SingleParameter *gate::ParametricRZ(UINT qubit_index, double initial_angle = 0.)¶
Function gate::Pauli¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_merge.hpp
-
QuantumGateBase *gate::Probabilistic(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list)¶
Function gate::ProbabilisticInstrument¶
Defined in File gate_merge.hpp
-
QuantumGateBase *gate::ProbabilisticInstrument(std::vector<double> distribution, std::vector<QuantumGateBase*> gate_list, UINT classical_register_address)¶
Function gate::RandomUnitary(std::vector<UINT>)¶
Defined in File gate_factory.hpp
-
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)¶
Defined in File gate_factory.hpp
-
QuantumGateMatrix *gate::RandomUnitary(std::vector<UINT> target_qubit_index_list, UINT seed)¶
Function gate::ReversibleBoolean¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RotInvX(UINT qubit_index, double angle)¶
Function gate::RotInvY¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RotInvY(UINT qubit_index, double angle)¶
Function gate::RotInvZ¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RotInvZ(UINT qubit_index, double angle)¶
Function gate::RotX¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RotX(UINT qubit_index, double angle)¶
Function gate::RotY¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RotY(UINT qubit_index, double angle)¶
Function gate::RotZ¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RotZ(UINT qubit_index, double angle)¶
Function gate::RX¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RX(UINT qubit_index, double angle)¶
Function gate::RY¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RY(UINT qubit_index, double angle)¶
Function gate::RZ¶
Defined in File gate_factory.hpp
-
ClsOneQubitRotationGate *gate::RZ(UINT qubit_index, double angle)¶
Function gate::S¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::S(UINT qubit_index)¶
Function gate::Sdag¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::Sdag(UINT qubit_index)¶
Function gate::SparseMatrix¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::sqrtX(UINT qubit_index)¶
Function gate::sqrtXdag¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::sqrtXdag(UINT qubit_index)¶
Function gate::sqrtY¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::sqrtY(UINT qubit_index)¶
Function gate::sqrtYdag¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::sqrtYdag(UINT qubit_index)¶
Function gate::StateReflection¶
Defined in File gate_factory.hpp
-
ClsStateReflectionGate *gate::StateReflection(const QuantumState *reflection_state)¶
量子状態に対して量子状態を反射する。
- Parameters
reflection_state – [in] 反射に用いられる量子状態
- Returns
作成されたゲートのインスタンス
Function gate::SWAP¶
Defined in File gate_factory.hpp
-
ClsTwoQubitGate *gate::SWAP(UINT qubit_index1, UINT qubit_index2)¶
Function gate::T¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::T(UINT qubit_index)¶
Function gate::Tdag¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::Tdag(UINT qubit_index)¶
Function gate::to_matrix_gate¶
Defined in File gate_merge.hpp
-
QuantumGateMatrix *gate::to_matrix_gate(const QuantumGateBase *gate)¶
Function gate::TwoQubitDepolarizingNoise¶
Defined in File gate_factory.hpp
-
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¶
Defined in File gate_factory.hpp
-
QuantumGateMatrix *gate::U1(UINT qubit_index, double lambda)¶
Function gate::U2¶
Defined in File gate_factory.hpp
-
QuantumGateMatrix *gate::U2(UINT qubit_index, double phi, double lambda)¶
Function gate::U3¶
Defined in File gate_factory.hpp
-
QuantumGateMatrix *gate::U3(UINT qubit_index, double theta, double phi, double lambda)¶
Function gate::X¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::X(UINT qubit_index)¶
Function gate::Y¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::Y(UINT qubit_index)¶
Function gate::Z¶
Defined in File gate_factory.hpp
-
ClsOneQubitGate *gate::Z(UINT qubit_index)¶
Function get_Pauli_matrix¶
Defined in File utility.hpp
-
void get_Pauli_matrix(ComplexMatrix &matrix, const std::vector<UINT> &pauli_id_list)¶
Function Igate_idling¶
Defined in File gate_named_one.hpp
-
static void Igate_idling(UINT, CTYPE*, ITYPE)¶
Function Igate_idling_gpu¶
Defined in File gate_named_one.hpp
-
static void Igate_idling_gpu(UINT, void*, ITYPE, void*, UINT)¶
Function KAK_decomposition¶
Defined in File matrix_decomposition.hpp
-
KAK_data KAK_decomposition(QuantumGateBase *target_gate, std::vector<UINT> target_bits)¶
Function KAK_decomposition_internal¶
Defined in File matrix_decomposition.hpp
-
KAK_data KAK_decomposition_internal(QuantumGateBase *target_gate)¶
Function loss_function::cross_entropy¶
Defined in File loss_function.hpp
-
double loss_function::cross_entropy(const std::vector<double> &prediction, const std::vector<double> &correct_label)¶
Template Function loss_function::L2_distance¶
Defined in File loss_function.hpp
Function loss_function::softmax_cross_entropy¶
Defined in File loss_function.hpp
-
double loss_function::softmax_cross_entropy(const std::vector<double> &prediction, const std::vector<double> &correct_label)¶
Function loss_function::softmax_cross_entropy_category¶
Defined in File loss_function.hpp
-
double loss_function::softmax_cross_entropy_category(std::vector<double> prediction, UINT correct_label)¶
Function observable::create_observable_from_openfermion_file¶
Defined in File observable.hpp
-
HermitianQuantumOperator *observable::create_observable_from_openfermion_file(std::string file_path)¶
Function observable::create_observable_from_openfermion_text¶
Defined in File observable.hpp
-
HermitianQuantumOperator *observable::create_observable_from_openfermion_text(const std::string &text)¶
Function observable::create_split_observable¶
Defined in File observable.hpp
-
std::pair<HermitianQuantumOperator*, HermitianQuantumOperator*> observable::create_split_observable(std::string file_path)¶
Function parse_openfermion_line¶
Defined in File utility.hpp
-
std::tuple<double, double, std::string> parse_openfermion_line(std::string line)¶
Function quantum_operator::create_general_quantum_operator_from_openfermion_file¶
Defined in File general_quantum_operator.hpp
-
GeneralQuantumOperator *quantum_operator::create_general_quantum_operator_from_openfermion_file(std::string file_path)¶
Function quantum_operator::create_general_quantum_operator_from_openfermion_text¶
Defined in File general_quantum_operator.hpp
-
GeneralQuantumOperator *quantum_operator::create_general_quantum_operator_from_openfermion_text(std::string text)¶
Function quantum_operator::create_split_general_quantum_operator¶
Defined in File general_quantum_operator.hpp
-
std::pair<GeneralQuantumOperator*, GeneralQuantumOperator*> quantum_operator::create_split_general_quantum_operator(std::string file_path)¶
Function rtrim¶
Defined in File utility.hpp
-
std::string &rtrim(std::string &str)¶
Function so4_to_magic_su2s¶
Defined in File matrix_decomposition.hpp
Function split¶
Defined in File utility.hpp
-
std::vector<std::string> split(const std::string &s, const std::string &delim)¶
Function state::drop_qubit¶
Defined in File state.hpp
-
QuantumState *state::drop_qubit(const QuantumState *state, std::vector<UINT> target, std::vector<UINT> projection)¶
Function state::inner_product¶
Defined in File state.hpp
-
CPPCTYPE state::inner_product(const QuantumState *state_bra, const QuantumState *state_ket)¶
Function state::make_mixture¶
Defined in File state_dm.hpp
-
DensityMatrixCpu *state::make_mixture(CPPCTYPE prob1, const QuantumStateBase *state1, CPPCTYPE prob2, const QuantumStateBase *state2)¶
Function state::make_superposition¶
Defined in File state.hpp
-
QuantumState *state::make_superposition(CPPCTYPE coef1, const QuantumState *state1, CPPCTYPE coef2, const QuantumState *state2)¶
Function state::partial_trace(const QuantumStateCpu *, std::vector<UINT>)¶
Defined in File state_dm.hpp
-
DensityMatrixCpu *state::partial_trace(const QuantumStateCpu *state, std::vector<UINT> target)¶
Function state::partial_trace(const DensityMatrixCpu *, std::vector<UINT>)¶
Defined in File state_dm.hpp
-
DensityMatrixCpu *state::partial_trace(const DensityMatrixCpu *state, std::vector<UINT> target_traceout)¶
Function state::permutate_qubit(const QuantumState *, std::vector<UINT>)¶
Defined in File state.hpp
-
QuantumState *state::permutate_qubit(const QuantumState *state, std::vector<UINT> qubit_order)¶
Function state::permutate_qubit(const DensityMatrixCpu *, std::vector<UINT>)¶
Defined in File state_dm.hpp
-
DensityMatrixCpu *state::permutate_qubit(const DensityMatrixCpu *state, std::vector<UINT> qubit_order)¶
Function state::tensor_product(const QuantumState *, const QuantumState *)¶
Defined in File state.hpp
-
QuantumState *state::tensor_product(const QuantumState *state_left, const QuantumState *state_right)¶
Function state::tensor_product(const DensityMatrixCpu *, const DensityMatrixCpu *)¶
Defined in File state_dm.hpp
-
DensityMatrixCpu *state::tensor_product(const DensityMatrixCpu *state_bra, const DensityMatrixCpu *state_ket)¶
Function to_general_quantum_operator¶
Defined in File gate_to_gqo.hpp
-
GeneralQuantumOperator *to_general_quantum_operator(const QuantumGateBase *gate, UINT GQO_qubits, double tol = 1e-6)¶
Variables¶
Variable invalid_qubit¶
Defined in File qubit_info.hpp
-
const UINT invalid_qubit = 9999¶
Variable KAK_GAMMA¶
Defined in File matrix_decomposition.hpp
-
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¶
Defined in File matrix_decomposition.hpp
-
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¶
Defined in File matrix_decomposition.hpp
-
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¶
Defined in File differential.hpp
-
_USE_MATH_DEFINES¶
Define DllExport¶
Defined in File type.hpp
-
DllExport¶
Define FLAG_CLIFFORD¶
Defined in File gate.hpp
-
FLAG_CLIFFORD¶
Flgas for gate property: gate is Clifford.
Define FLAG_GAUSSIAN¶
Defined in File gate.hpp
-
FLAG_GAUSSIAN¶
Flgas for gate property: gate is Gaussian.
Define FLAG_PARAMETRIC¶
Defined in File gate.hpp
-
FLAG_PARAMETRIC¶
Flgas for gate property: gate is parametrized.
Define FLAG_PAULI¶
Defined in File gate.hpp
-
FLAG_PAULI¶
Flgas for gate property: gate is Pauli.
Regulation for argument/qubit/index ordering Read this before treating kronecker product
— arguments — 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)
— state — 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.
— gate — 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¶
Defined in File qubit_info.hpp
-
FLAG_X_COMMUTE¶
Flags for bit property: diagonal in X-basis.
Define FLAG_Y_COMMUTE¶
Defined in File qubit_info.hpp
-
FLAG_Y_COMMUTE¶
Flags for bit property: diagonal in Y-basis.
Define FLAG_Z_COMMUTE¶
Defined in File qubit_info.hpp
-
FLAG_Z_COMMUTE¶
Flags for bit property: diagonal in Z-basis.
Typedefs¶
Typedef ComplexMatrix¶
Defined in File type.hpp
Typedef ComplexVector¶
Defined in File type.hpp
-
using ComplexVector = Eigen::VectorXcd¶
Typedef CPPCTYPE¶
Defined in File type.hpp
-
using CPPCTYPE = std::complex<double>¶
Typedef DensityMatrix¶
Defined in File state_dm.hpp
-
using DensityMatrix = DensityMatrixCpu¶
Typedef Observable¶
Defined in File circuit.hpp
-
using Observable = HermitianQuantumOperator¶
Typedef Observable¶
Defined in File observable.hpp
-
using Observable = HermitianQuantumOperator
Typedef Observable¶
Defined in File simulator.hpp
-
using Observable = HermitianQuantumOperator
Typedef QuantumGate_Instrument¶
Defined in File gate_general.hpp
-
using QuantumGate_Instrument = QuantumGate_CPTP¶
Typedef QuantumGate_OneControlOneTarget¶
Defined in File gate_named_two.hpp
-
using QuantumGate_OneControlOneTarget = ClsOneControlOneTargetGate¶
Typedef QuantumGate_OneQubit¶
Defined in File gate_named_one.hpp
-
using QuantumGate_OneQubit = ClsOneQubitGate¶
Typedef QuantumGate_OneQubitRotation¶
Defined in File gate_named_one.hpp
-
using QuantumGate_OneQubitRotation = ClsOneQubitRotationGate¶
Typedef QuantumGate_ProbabilisticInstrument¶
Defined in File gate_general.hpp
-
using QuantumGate_ProbabilisticInstrument = QuantumGate_Probabilistic¶
This type alias is kept for backward compatibility. Do not edit this!
Typedef QuantumGate_TwoQubit¶
Defined in File gate_named_two.hpp
-
using QuantumGate_TwoQubit = ClsTwoQubitGate¶
Typedef QuantumState¶
Defined in File state.hpp
-
using QuantumState = QuantumStateCpu¶
Typedef SparseComplexMatrix¶
Defined in File type.hpp
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.
Fork the
Qulacs
repo on GitHub.Clone your fork locally:
$ git clone git@github.com:qulacs/qulacs.git
Create a branch for local development:
$ git checkout -b name-of-your-bugfix-or-feature
Now you can make your changes locally.
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.
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
Submit a pull request through the GitHub website.
Pull Request Guidelines¶
Before you submit a pull request, check that it meets these guidelines:
The pull request should include tests.
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.
The pull request should work for both python and C++.