{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Qulacs Python Advanced Guide\n", "\n", "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.." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Quantum States\n", "This class allocates and manages $2^n$ complex arrays on the CPU/GPU with the precision of complex128." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Create and Destroy\n", "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`." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " *** Quantum State ***\n", " * Qubit Count : 2\n", " * Dimension : 4\n", " * State vector : \n", "(1,0)\n", "(0,0)\n", "(0,0)\n", "(0,0)\n", "\n" ] } ], "source": [ "from qulacs import QuantumState\n", "n = 2\n", "state = QuantumState(n)\n", "print(state)\n", "del state\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Transform between quantum state and numpy array\n", "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.\n", "While `get_vector` returns all the element as an array, `get_amplitude` can be used to quickly get a single element." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "[0.+0.j 1.+0.j 2.+0.j 3.+0.j]\n", "(2+0j)\n" ] } ], "source": [ "from qulacs import QuantumState\n", "\n", "state = QuantumState(2)\n", "vec = state.get_vector()\n", "print(vec)\n", "state.load([0,1,2,3])\n", "print(state.get_vector())\n", "print(state.get_amplitude(2))\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Copy quantum states\n", "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." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "from qulacs import QuantumState\n", "\n", "initial_state = QuantumState(3)\n", "buffer = initial_state.allocate_buffer()\n", "for ind in range(10):\n", " buffer.load(initial_state)\n", " # some computation and get results\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Store quantum state\n", "Quantum states can be converted to JSON string.\n", "You can restore a quantum state by loading JSON." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "original: [-0.53409555-0.11980945j 0.23272193+0.42256166j -0.65314356-0.07012461j\n", " -0.02987127+0.18778582j]\n", "restored: [-0.53409555-0.11980945j 0.23272193+0.42256166j -0.65314356-0.07012461j\n", " -0.02987127+0.18778582j]\n" ] } ], "source": [ "from qulacs import QuantumState\n", "from qulacs import state\n", "\n", "o_state = QuantumState(2)\n", "o_state.set_Haar_random_state()\n", "print(\"original:\", o_state.get_vector())\n", "state_json = o_state.to_json()\n", "\n", "r_state = state.from_json(state_json)\n", "print(\"restored:\", r_state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Quantum states can also be saved to files in pickle format." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "from qulacs import QuantumState\n", "import pickle\n", "\n", "state = QuantumState(2)\n", "\n", "# store\n", "with open('state.pickle', 'wb') as f:\n", " pickle.dump(state, f)\n", "\n", "# load\n", "with open('state.pickle', 'rb') as f:\n", " state = pickle.load(f)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Initialization of quantum state\n", "The following is an function initializing a quantum state to a specific state." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "[-0.08457288-0.14143014j -0.13386446+0.11328032j -0.22521966-0.16546737j\n", " -0.15105932+0.48125064j -0.45087363+0.17271267j -0.05855838+0.32498025j\n", " 0.35972119+0.02643361j -0.10103482-0.35651694j]\n" ] } ], "source": [ "from qulacs import QuantumState\n", "\n", "n = 3\n", "state = QuantumState(n)\n", "# Initialize as |0> state\n", "state.set_zero_state()\n", "print(state.get_vector())\n", "\n", "# Initialize the specified value to the calculation base in binary notation\n", "state.set_computational_basis(0b101)\n", "print(state.get_vector())\n", "\n", "# Initialize to random pure state with Haar measure using argument value as seed\n", "# If no value is specified, the time function is used as a seed. Pseudo random number uses xorshift.\n", "state.set_Haar_random_state(0)\n", "print(state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Check quantum state\n", "The following example is a list of functions to check quantum state information without changing the quantum state." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "qubit_count 5\n", "zero_prob_1 0.4601075596424598\n", "marginal_prob 0.20030608663813237\n", "entropy 3.1082736424124735\n", "sqaured_norm 0.9999999999999999\n", "sampling [11, 18, 12, 29, 21, 13, 28, 24, 10, 22]\n", "sampling (with seed) [23, 18, 28, 14, 17, 30, 9, 17, 16, 10]\n", "device cpu\n" ] } ], "source": [ "from qulacs import QuantumState\n", "\n", "n = 5\n", "state = QuantumState(n)\n", "state.set_Haar_random_state(0)\n", "\n", "# Get quantum bit numbers\n", "qubit_count = state.get_qubit_count()\n", "print(\"qubit_count\", qubit_count)\n", "\n", "# Get the probability that the specified qubit will be measured as 0\n", "prob = state.get_zero_probability(1)\n", "print(\"zero_prob_1\", prob)\n", "\n", "# Get arbitrary marginal probabilities\n", "# Argument is an array of the same length as the number of qubits\n", "# Specify 0,1,2. 0,1 is the probability of the subscript measured at that value\n", "# 2 means that bit is peripheralized.\n", "# For example, calculation of the probability that the third is measured as 0 and the 0th is measured as 1:\n", "prob = state.get_marginal_probability([1,2,2,0,2])\n", "print(\"marginal_prob\", prob)\n", "\n", "# Get the entropy of the probability distribution when measured on the Z basis\n", "ent = state.get_entropy()\n", "print(\"entropy\", ent)\n", "\n", "# Get squared norm ()\n", "# Because the operation may not be Trace preserving, the norm of state does not necessarily to be 1.\n", "sq_norm = state.get_squared_norm()\n", "print(\"sqaured_norm\", sq_norm)\n", "\n", "# Measure and sample all the qubits on Z-basis as many times as given by the argument. \n", "# Returns a list of integers converted from the resulting binaries.\n", "samples = state.sampling(10)\n", "print(\"sampling\", samples)\n", "\n", "# You can supply a random seed as second argument.\n", "# If the same seed is given, always returns the same sampling result.\n", "samples_with_seed = state.sampling(10, 314)\n", "print(\"sampling (with seed)\", samples_with_seed)\n", "\n", "# Get a character string indicating whether the state vector is on CPU or GPU\n", "dev_type = state.get_device_name()\n", "print(\"device\", dev_type)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Deformation of quantum state\n", "The following functions modify a quantum state." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "state [1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "buffer [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "added [1.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "mul_coef [0.5+0.1j 0. +0.j 0.5+0.1j 0. +0.j ]\n", "mul_elementwise_func [ 0.5+0.1j 0. +0.j -0.5-0.1j 0. -0.j ]\n", "sq_norm 0.52\n", "normalized [ 0.69337525+0.13867505j 0. +0.j -0.69337525-0.13867505j\n", " 0. -0.j ]\n", "sq_norm 0.9999999999999998\n" ] } ], "source": [ "from qulacs import QuantumState\n", "state = QuantumState(2)\n", "state.set_computational_basis(0)\n", "buffer = QuantumState(2)\n", "buffer.set_computational_basis(2)\n", "print(\"state\" , state.get_vector())\n", "print(\"buffer\", buffer.get_vector())\n", "\n", "# Sum of quantum state (state <- state+buffer)\n", "# Add the buffer state to the state to create a superposition state.\n", "# The norm after the operation generally is not 1.\n", "state.add_state(buffer)\n", "print(\"added\", state.get_vector())\n", "\n", "# Product of quantum state and complex number\n", "# Multiplies all elements by the complex number of the argument. \n", "# The norm after operation generally is not 1.\n", "coef = 0.5 + 0.1j\n", "state.multiply_coef(coef)\n", "print(\"mul_coef\", state.get_vector())\n", "\n", "# Pruduct of a quantum state and complex numbers specified by an index of each element\n", "# Multiplies the amplitude of |00> by `coef_func(0)`, the amplitude of |01> by `coef_func(1)`.\n", "# The norm after operation generally is not 1.\n", "def coef_func(i: int) -> complex:\n", " assert 0 <= i < 2**2\n", " return 1j**i\n", "state.multiply_elementwise_function(coef_func)\n", "print(\"mul_elementwise_func\", state.get_vector())\n", "\n", "# Normalize quantum states\n", "# Provide the current squared norm as an argument.\n", "squared_norm = state.get_squared_norm()\n", "print(\"sq_norm\", squared_norm)\n", "state.normalize(squared_norm)\n", "print(\"normalized\", state.get_vector())\n", "print(\"sq_norm\", state.get_squared_norm())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Operation on classic registers\n", "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." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "20\n" ] } ], "source": [ "from qulacs import QuantumState\n", "state = QuantumState(3)\n", "position = 0\n", "# Write the value to `position`-th register\n", "state.set_classical_value(position, 20)\n", "# Get the value of the `position`-th register\n", "obtained = state.get_classical_value(position)\n", "print(obtained)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Calculation between quantum states\n", "The inner product and tensor product between quantum states can be obtained by `inner_product` and `tensor_product` respectively." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(-0.056292589186392766-0.06355316981838662j)\n", "[0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n" ] } ], "source": [ "from qulacs import QuantumState\n", "from qulacs.state import inner_product, tensor_product\n", "\n", "n = 5\n", "state_bra = QuantumState(n)\n", "state_ket = QuantumState(n)\n", "state_bra.set_Haar_random_state()\n", "state_ket.set_computational_basis(0)\n", "\n", "# Calculation of inner product\n", "value = inner_product(state_bra, state_ket)\n", "print(value)\n", "\n", "n1 = 1\n", "state_ket1 = QuantumState(n1)\n", "state_ket1.set_computational_basis(1)\n", "n2 = 2\n", "state_ket2 = QuantumState(n2)\n", "state_ket2.set_computational_basis(2)\n", "\n", "# Calculation of tensor product\n", "tensor_product_state = tensor_product(state_ket1, state_ket2)\n", "print(tensor_product_state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Swap and delete qubits\n", "You can swap indices of a qubit with `permutate_qubit()`.\n", "You can get a projection onto a specified qubit with `drop_qubit()`." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "original: [ 0.04935285-0.33525621j -0.40848741-0.16861513j 0.0877062 +0.3016868j\n", " 0.43151866+0.12561444j 0.05137289-0.07313601j 0.10155306-0.05927549j\n", " 0.12474423-0.07303469j 0.23710293+0.53875064j]\n", "permutate: [ 0.04935285-0.33525621j 0.0877062 +0.3016868j 0.05137289-0.07313601j\n", " 0.12474423-0.07303469j -0.40848741-0.16861513j 0.43151866+0.12561444j\n", " 0.10155306-0.05927549j 0.23710293+0.53875064j]\n", "\n", "original: [-0.13129252+0.41425428j -0.06117213+0.11127952j -0.30889329-0.26279468j\n", " -0.14177694+0.05919262j 0.03556784-0.19266318j -0.24280479-0.45063361j\n", " 0.383783 -0.0233139j 0.34842192+0.19315843j]\n", "projection to 0: [-0.13129252+0.41425428j -0.06117213+0.11127952j 0.03556784-0.19266318j\n", " -0.24280479-0.45063361j]\n", "projection to 1: [-0.30889329-0.26279468j -0.14177694+0.05919262j 0.383783 -0.0233139j\n", " 0.34842192+0.19315843j]\n" ] } ], "source": [ "from qulacs import QuantumState\n", "from qulacs.state import permutate_qubit, drop_qubit\n", "\n", "n = 3\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "print(\"original:\", state.get_vector())\n", "# new qubit 0 is old qubit 1\n", "# new qubit 1 is old qubit 2, \n", "# new qubit 2 is old qubit 0, \n", "permutate = permutate_qubit(state, [1, 2, 0])\n", "print(\"permutate:\", permutate.get_vector())\n", "print()\n", "\n", "n = 3\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "print(\"original:\", state.get_vector())\n", "state0 = drop_qubit(state, [1], [0])\n", "print(\"projection to 0:\", state0.get_vector()) # projection: qubit 1 is 0\n", "state1 = drop_qubit(state, [1], [1])\n", "print(\"projection to 1:\", state1.get_vector()) # projection: qubit 1 is 1\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Calculate partial trace\n", "With `partial_trace()`, you can obtain a partial trace of a given qubit of a given quantum state as a density matrix.\n", "The indices of the converted qubits are reassigned based on the order of the qubits before conversion." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0. +0.j 0. +0.j 0.70710678+0.j 0.70710678+0.j\n", " 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", "[[0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", " [0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n", "[[0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [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]\n", " [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]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n", "[[0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", " [0.5+0.j 0.5+0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n" ] } ], "source": [ "from qulacs import QuantumState, DensityMatrix\n", "from qulacs.gate import H, X\n", "from qulacs.state import partial_trace\n", "\n", "state = QuantumState(3)\n", "state.set_computational_basis(0)\n", "H(0).update_quantum_state(state)\n", "X(1).update_quantum_state(state)\n", "print(state.get_vector())\n", "\n", "trace = partial_trace(state, [1])\n", "print(trace.get_matrix())\n", "\n", "dm_state = DensityMatrix(3)\n", "dm_state.set_computational_basis(0)\n", "H(0).update_quantum_state(dm_state)\n", "X(1).update_quantum_state(dm_state)\n", "print(dm_state.get_matrix())\n", "\n", "trace = partial_trace(dm_state, [1])\n", "print(trace.get_matrix())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Calculation using GPU\n", "When Qulacs is installed from qulacs-gpu package, `QuantumStateGpu` is available. Except the different class name, the usage is the same as `QuantumState`." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "```python\n", "from qulacs import QuantumStateGpu\n", "state = QuantumStateGpu(2)\n", "print(state)\n", "# print(state.get_device_name())\n", "# gpu\n", "```" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Though the usage is the same as `QuantumState`, there are two aspects to keep in mind:\n", "\n", "* The `get_vector` function takes a long time because it requires copying between the GPU and CPU. This function should be avoided whenever possible.\n", "* `inner_product` between CPU / GPU states cannot be calculated. It is possible to `load` a state vector between the GPU and CPU state vectors, but it is time consuming and should be avoided." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## DensityMatrix\n", "\n", "`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.\n", "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$.\n", "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.\n", "Basically, `DensityMatrix` can be operated in the same way as `QuantumState`.\n", "\n", "### Generate and delete\n", "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." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " *** Density Matrix ***\n", " * Qubit Count : 2\n", " * Dimension : 4\n", " * Density matrix : \n", "(1,0) (0,0) (0,0) (0,0)\n", "(0,0) (0,0) (0,0) (0,0)\n", "(0,0) (0,0) (0,0) (0,0)\n", "(0,0) (0,0) (0,0) (0,0)\n", "\n" ] } ], "source": [ "from qulacs import DensityMatrix\n", "\n", "n = 2\n", "state = DensityMatrix(n)\n", "print(state)\n", "del state\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Conversion between quantum states and numpy array\n", "You can convert quantum states and numpy array mutually with `get_matrix` and `load`.\n", "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.\n", "Basically, whether the norm is conserved or not is not checked." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "[[0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 1.+0.j 2.+0.j 3.+0.j]\n", " [0.+0.j 2.+0.j 4.+0.j 6.+0.j]\n", " [0.+0.j 3.+0.j 6.+0.j 9.+0.j]]\n", "[[0.+0.j 1.+0.j 2.+0.j 3.+0.j]\n", " [1.+0.j 2.+0.j 3.+0.j 4.+0.j]\n", " [2.+0.j 3.+0.j 4.+0.j 5.+0.j]\n", " [3.+0.j 4.+0.j 5.+0.j 6.+0.j]]\n" ] } ], "source": [ "from qulacs import DensityMatrix\n", "\n", "state = DensityMatrix(2)\n", "mat = state.get_matrix()\n", "print(mat)\n", "state.load([0,1,2,3])\n", "print(state.get_matrix())\n", "state.load([[0,1,2,3], [1,2,3,4], [2,3,4,5], [3,4,5,6]])\n", "print(state.get_matrix())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Copy between quantum states\n", "A quantum state can be instantiated by `copy` to create a new instance of itself.\n", "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.\n", "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." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "from qulacs import QuantumState, DensityMatrix\n", "\n", "initial_state = DensityMatrix(3)\n", "copied_state = initial_state.copy()\n", "buffer = initial_state.allocate_buffer()\n", "buffer.load(initial_state)\n", "state_vector = QuantumState(3)\n", "buffer.load(state_vector)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Store quantum states\n", "`DensityMatrix` can also be converted to/from JSON string" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "original: [[ 0.69553616+0.j -0.30796432+0.24210111j -0.00753329-0.048494j\n", " -0.16911174-0.16523753j]\n", " [-0.30796432-0.24210111j 0.22062831+0.j -0.01354418+0.02409399j\n", " 0.01736242+0.13202679j]\n", " [-0.00753329+0.048494j -0.01354418-0.02409399j 0.00346268+0.j\n", " 0.01335228-0.01000109j]\n", " [-0.16911174+0.16523753j 0.01736242-0.13202679j 0.01335228+0.01000109j\n", " 0.08037285+0.j ]]\n", "restored: [[ 0.69553616+0.j -0.30796432+0.24210111j -0.00753329-0.048494j\n", " -0.16911174-0.16523753j]\n", " [-0.30796432-0.24210111j 0.22062831+0.j -0.01354418+0.02409399j\n", " 0.01736242+0.13202679j]\n", " [-0.00753329+0.048494j -0.01354418-0.02409399j 0.00346268+0.j\n", " 0.01335228-0.01000109j]\n", " [-0.16911174+0.16523753j 0.01736242-0.13202679j 0.01335228+0.01000109j\n", " 0.08037285+0.j ]]\n" ] } ], "source": [ "from qulacs import DensityMatrix\n", "from qulacs import state\n", "\n", "o_state = DensityMatrix(2)\n", "o_state.set_Haar_random_state()\n", "print(\"original:\", o_state.get_matrix())\n", "state_json = o_state.to_json()\n", "\n", "r_state = state.from_json(state_json)\n", "print(\"restored:\", r_state.get_matrix())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Density matrices can be stored to files in pickle format." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "from qulacs import QuantumState\n", "import pickle\n", "\n", "state = QuantumState(2)\n", "\n", "# store\n", "with open('state.pickle', 'wb') as f:\n", " pickle.dump(state, f)\n", "\n", "# load\n", "with open('state.pickle', 'rb') as f:\n", " state = pickle.load(f)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Initialize quantum states\n", "The following example shows functions to initialize a quantum state to a specific pure state." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "[[0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "[[ 0.06955138+0.j -0.01203783+0.07302921j 0.10872467+0.04574116j\n", " -0.14160694+0.15896533j]\n", " [-0.01203783-0.07302921j 0.07876443+0.j 0.02921052-0.12207811j\n", " 0.19142327+0.12117438j]\n", " [ 0.10872467-0.04574116j 0.02921052+0.12207811j 0.20004359+0.j\n", " -0.11681879+0.3416283j ]\n", " [-0.14160694-0.15896533j 0.19142327-0.12117438j -0.11681879-0.3416283j\n", " 0.6516406 +0.j ]]\n" ] } ], "source": [ "from qulacs import DensityMatrix\n", "\n", "n = 2\n", "state = DensityMatrix(n)\n", "\n", "# Initialize as |0> state.\n", "state.set_zero_state()\n", "print(state.get_matrix())\n", "\n", "# Initialize as computational basis specified in binary format.\n", "state.set_computational_basis(0b10)\n", "print(state.get_matrix())\n", "\n", "\n", "# Initialize as a random pure state in Haar measure with the seed given as an argument.\n", "# If you do not give the seed, `time` function is used for seed.\n", "# Xorshift is used for psuedo random.\n", "state.set_Haar_random_state(0)\n", "print(state.get_matrix())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Check quantum states\n", "The following example shows functions to check information of quantum states without changing the states." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "qubit_count 5\n", "zero_prob_1 0.46010755964245986\n", "marginal_prob 0.20030608663813237\n", "entropy 3.108273642412474\n", "sqaured_norm 1.0000000000000002\n", "sampling [11, 30, 30, 30, 24, 6, 24, 3, 10, 29]\n", "sampling (with seed) [23, 18, 28, 14, 17, 30, 9, 17, 16, 10]\n", "device cpu\n" ] } ], "source": [ "from qulacs import DensityMatrix\n", "\n", "n = 5\n", "state = DensityMatrix(n)\n", "state.set_Haar_random_state(0)\n", "\n", "# Get quantum bit numbers\n", "qubit_count = state.get_qubit_count()\n", "print(\"qubit_count\", qubit_count)\n", "\n", "# Get the probability that the specified qubit will be measured as 0\n", "prob = state.get_zero_probability(1)\n", "print(\"zero_prob_1\", prob)\n", "\n", "# Get arbitrary marginal probabilities\n", "# Argument is an array of the same length as the number of qubits\n", "# Specify 0,1,2. 0,1 is the probability of the subscript measured at that value\n", "# 2 means that bit is peripheralized.\n", "# For example, calculation of the probability that the third is measured as 0 and the 0th is measured as 1:\n", "prob = state.get_marginal_probability([1,2,2,0,2])\n", "print(\"marginal_prob\", prob)\n", "\n", "# Get the entropy of the probability distribution when measured on the Z basis\n", "ent = state.get_entropy()\n", "print(\"entropy\", ent)\n", "\n", "# Get squared norm ()\n", "# Because the operation may not be Trace preserving, the norm of state does not necessarily to be 1.\n", "sq_norm = state.get_squared_norm()\n", "print(\"sqaured_norm\", sq_norm)\n", "\n", "# Measure and sample all the qubits on Z-basis as many times as given by the argument. \n", "# Returns a list of integers converted from the resulting binaries.\n", "samples = state.sampling(10)\n", "print(\"sampling\", samples)\n", "\n", "# You can supply a random seed as second argument.\n", "# If the same seed is given, always returns the same sampling result.\n", "samples_with_seed = state.sampling(10, 314)\n", "print(\"sampling (with seed)\", samples_with_seed)\n", "\n", "# Get a character string indicating whether the state vector is on CPU or GPU\n", "dev_type = state.get_device_name()\n", "print(\"device\", dev_type)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Deformation of quantum states\n", "The following functions modify a quantum state.\n", "`add_state` and `multiply_coef` calculates for each element in a density matrix.\n", "\n", "**It is fundamentally different in behavior from the operation of the same name in `QuantumState`, which corresponds to the quantum state**\n", "\n", "- `add_state` of `QuantumState` creates superpositon, but `add_state` of `DensityMatrix` create mixed state\n", "- The operation corresponding to `multiply_coef(z)` of `QuantumState` is `multiply_coef(abs(z)**2)` for `DensityMatrix`\n", "\n", "Using `state.make_superposition()` `state.make_mixture()` is recommended since `add_state()` `multiply_coef()` make users confused with those generated by `QuantumState`." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "state [[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "buffer [[0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "added [[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "mul_coef [[3.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 3.+0.j 0.+0.j]\n", " [0.+0.j 0.+0.j 0.+0.j 0.+0.j]]\n", "sq_norm 6.0\n", "normalized [[0.5+0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0.5+0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]]\n", "sq_norm 1.0\n" ] } ], "source": [ "from qulacs import DensityMatrix\n", "state = DensityMatrix(2)\n", "state.set_computational_basis(0)\n", "buffer = DensityMatrix(2)\n", "buffer.set_computational_basis(2)\n", "print(\"state\" , state.get_matrix())\n", "print(\"buffer\", buffer.get_matrix())\n", "\n", "# Sum of quantum state (state <- state+buffer)\n", "# Add the buffer state to the state to create a superposition state.\n", "# The norm after the operation generally is not 1.\n", "state.add_state(buffer)\n", "print(\"added\", state.get_matrix())\n", "\n", "# Product of quantum state and complex number\n", "# Multiplies all elements by the complex number of the argument. \n", "# The norm after operation generally is not 1.\n", "coef = 3.0\n", "state.multiply_coef(coef)\n", "print(\"mul_coef\", state.get_matrix())\n", "\n", "# Normalize quantum states\n", "# Provide the current squared norm as an argument.\n", "squared_norm = state.get_squared_norm()\n", "print(\"sq_norm\", squared_norm)\n", "state.normalize(squared_norm)\n", "print(\"normalized\", state.get_matrix())\n", "print(\"sq_norm\", state.get_squared_norm())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Operation on classical registers\n", "`DensityMatrix` also has classical registers as integer arrays with variable length." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "20\n" ] } ], "source": [ "from qulacs import DensityMatrix\n", "state = DensityMatrix(3)\n", "position = 0\n", "# Set the value at `position`-th register.\n", "state.set_classical_value(position, 20)\n", "# Get the value at `position`-th register.\n", "obtained = state.get_classical_value(position)\n", "print(obtained)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Creating superposition states and mixture states\n", "\n", "You can create superposition states and mixture states by using `make_superposition()` `make_mixture()` in `state` module.\n", "These states can also be created by applying `add_state()` `multiply_coef()` to `QuantumState` `DensityMatrix`, but is deprecated due to low readability." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.5+0.j 0. +0.j 0. +0.j 0.5+0.j]\n", "[[0.5+0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n", " [0. +0.j 0. +0.j 0. +0.j 0.5+0.j]]\n" ] } ], "source": [ "from qulacs import QuantumState, DensityMatrix\n", "from qulacs.state import make_superposition, make_mixture\n", "# from QuantumState |a> and |b>, create a superposition state p|a> + q|b>\n", "a = QuantumState(2)\n", "a.set_computational_basis(0b00)\n", "b = QuantumState(2)\n", "b.set_computational_basis(0b11)\n", "p = 1 / 2\n", "q = 1 / 2\n", "c = make_superposition(p, a, q, b)\n", "print(c.get_vector())\n", "# from QuantumState |a> and DensityMatrix |b><00| + |11><11|\n", "proj_00_or_11 = add(gate00, gate11)\n", "print(proj_00_or_11)\n", "\n", "gate_ii_zz = add(Identity(0), merge(Z(0),Z(1)))\n", "gate_ii_xx = add(Identity(0), merge(X(0),X(1)))\n", "proj_00_plus_11 = merge(gate_ii_zz, gate_ii_xx)\n", "# ((|00>+|11>)(<00|+<11|))/2 = (II + ZZ)(II + XX)/4\n", "proj_00_plus_11.multiply_scalar(0.25)\n", "print(proj_00_plus_11)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Random unitary\n", "Use the `RandomUnitary` function to sample a random unitary matrix with the Haar measure and generate a dense matrix gate." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " *** gate info *** \n", " * gate name : DenseMatrix\n", " * target : \n", " 2 : commute \n", " 3 : commute \n", " * control : \n", " * Pauli : no\n", " * Clifford : no\n", " * Gaussian : no\n", " * Parametric: no\n", " * Diagonal : no\n", " * Matrix\n", " (-0.549679,-0.199309) (-0.41282,0.191987) (-0.430215,-0.393607) (-0.152234,-0.296078)\n", " (0.255527,0.290869) (0.136685,-0.154401) (0.0998426,-0.553577) (-0.700763,-0.0097331)\n", " (0.056699,0.690511) (-0.488394,-0.0743973) (0.0480177,-0.260356) (0.439362,0.113074)\n", " (0.156442,-0.0611172) (-0.695389,-0.150231) (0.177095,0.492055) (-0.433419,-0.0657552)\n", "\n" ] } ], "source": [ "from qulacs.gate import RandomUnitary\n", "target_list = [2,3]\n", "gate = RandomUnitary(target_list)\n", "print(gate)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Stochastic operation\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " *** gate info *** \n", " * gate name : Generic gate\n", " * target : \n", " * control : \n", " * Pauli : no\n", " * Clifford : no\n", " * Gaussian : no\n", " * Parametric: no\n", " * Diagonal : yes\n", "\n", "[0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "[0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "[0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "[ 0.+0.j -0.-0.j 1.+0.j -0.-0.j]\n", "[0. +0.j 0. +0.j 0.70710678+0.j 0.70710678+0.j]\n", "[0. +0.j 0. +0.j 0.70710678+0.j 0.70710678+0.j]\n", "[ 0. +0.j -0. -0.j 0.70710678+0.j -0.70710678-0.j]\n", "[ 0.70710678+0.j -0.70710678-0.j 0. +0.j -0. -0.j]\n", "[0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "[ 0.+0.j -1.-0.j 0.+0.j -0.-0.j]\n" ] } ], "source": [ "from qulacs.gate import Probabilistic, H, Z\n", "distribution = [0.2, 0.2, 0.2]\n", "gate_list = [H(0), Z(0), X(1)]\n", "gate = Probabilistic(distribution, gate_list)\n", "print(gate)\n", "\n", "from qulacs import QuantumState\n", "state = QuantumState(2)\n", "for _ in range(10):\n", " gate.update_quantum_state(state)\n", " print(state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "`BitFlipNoise`, `DephasingNoise`, `IndependentXZNoise`, `DepolarizingNoise`, and `TwoQubitDepolarizingNoise` gates are defined as stochastic gates. `Probabilistic` instances are generated by entering the error probabilities." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "[0.-0.j 0.+1.j 0.-0.j 0.+0.j]\n", "[0.-0.j 0.+1.j 0.-0.j 0.+0.j]\n", "[ 0.-0.j -0.-1.j 0.-0.j -0.-0.j]\n", "[0.+0.j 0.-0.j 0.+0.j 0.-1.j]\n", "[0.+0.j 0.-0.j 0.+0.j 0.-1.j]\n", "[-1.+0.j 0.+0.j -0.+0.j 0.+0.j]\n", "[ 0.-0.j 0.+0.j 0.+0.j -0.-1.j]\n", "[ 0.-0.j 0.+0.j 0.+0.j -0.-1.j]\n", "[ 0.-0.j 0.+0.j 0.+0.j -0.-1.j]\n" ] } ], "source": [ "from qulacs.gate import BitFlipNoise, DephasingNoise, IndependentXZNoise, DepolarizingNoise, TwoQubitDepolarizingNoise\n", "target = 0\n", "second_target = 1\n", "error_prob = 0.8\n", "gate = BitFlipNoise(target, error_prob) # X: prob\n", "gate = DephasingNoise(target, error_prob) # Z: prob\n", "gate = IndependentXZNoise(target, error_prob) # X,Z : prob*(1-prob), Y: prob*prob\n", "gate = DepolarizingNoise(target, error_prob) # X,Y,Z : prob/3\n", "gate = TwoQubitDepolarizingNoise(target, second_target, error_prob) # {I,X,Y,Z} \\times {I,X,Y,Z} \\setminus {II} : prob/15\n", "\n", "from qulacs import QuantumState\n", "state = QuantumState(2)\n", "for _ in range(10):\n", " gate.update_quantum_state(state)\n", " print(state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Noisy evolution\n", "There are two gates, `NoisyEvolution` and `NoisyEvolution_fast`, that interact from the environment and are attenuated by time evolution.\n", "They can be used by the following steps\n", "\n", "1. set up the system to be interacted with by the environment as a Hamiltonian and specify the operator of the interaction.\n", "2. specify the value to be evolved in time and the time to be varied microscopically.\n", "3. solve the differential equation.\n", " - `NoisyEvolution` solves differential equations using Runge-Kutta method.\n", " - `NoisyEvolution_fast` extracts a matrix and finds it by diagonalization.\n", "\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0] exp: -0.0006155544536970823\n", "[1] exp: -0.0006155544536970823\n", "[2] exp: 0.00028465213360111513\n", "[3] exp: -0.0003309023200959672\n", "[4] exp: -0.0009464567737930495\n", "[5] exp: -0.0009464567737930495\n", "[6] exp: -0.0009464567737930495\n", "[7] exp: -0.0009464567737930495\n", "[8] exp: -0.0009464567737930495\n", "[9] exp: -0.0015620112274901319\n", "[10] exp: -0.0022830973241566837\n", "[11] exp: -0.0022830973241566837\n", "[12] exp: -0.0022830973241566837\n", "[13] exp: -0.002898651777853766\n", "[14] exp: -0.002898651777853766\n", "[15] exp: -0.0035142062315508486\n", "[16] exp: -0.0035142062315508486\n", "[17] exp: -0.004129760685247931\n", "[18] exp: -0.004129760685247931\n", "[19] exp: -0.004745315138945013\n", "[20] exp: -0.004745315138945013\n", "[21] exp: -0.004745315138945013\n", "[22] exp: -0.005360869592642096\n", "[23] exp: -0.005976424046339178\n", "[24] exp: -0.006591978500036261\n", "[25] exp: -0.006591978500036261\n", "[26] exp: -0.006591978500036261\n", "[27] exp: -0.007207532953733343\n", "[28] exp: -0.007823087407430426\n", "[29] exp: -0.007823087407430426\n", "[30] exp: -0.008438641861127508\n", "[31] exp: -0.008438641861127508\n", "[32] exp: -0.00905419631482459\n", "[33] exp: -0.008646834619727773\n", "[34] exp: -0.009262389073424856\n", "[35] exp: -0.009877943527121938\n", "[36] exp: -0.01049349798081902\n", "[37] exp: -0.011419090630198456\n", "[38] exp: -0.012034645083895538\n", "[39] exp: -0.01265019953759262\n", "[40] exp: -0.01265019953759262\n", "[41] exp: -0.01265019953759262\n", "[42] exp: -0.013265753991289703\n", "[43] exp: -0.013692461721774537\n", "[44] exp: -0.01434682754881815\n", "[45] exp: -0.01434682754881815\n", "[46] exp: -0.014962382002515233\n", "[47] exp: -0.014962382002515233\n", "[48] exp: -0.015577936456212315\n", "[49] exp: -0.015577936456212315\n", "[50] exp: -0.016193490909909396\n", "[51] exp: -0.016809045363606476\n", "[52] exp: -0.017424599817303557\n", "[53] exp: -0.018040154271000638\n", "[54] exp: -0.01865570872469772\n", "[55] exp: -0.0192712631783948\n", "[56] exp: -0.01988681763209188\n", "[57] exp: -0.02050237208578896\n", "[58] exp: -0.02111792653948604\n", "[59] exp: -0.022007366313092046\n", "[60] exp: -0.022007366313092046\n", "[61] exp: -0.02139181185939496\n", "[62] exp: -0.022007366313092042\n", "[63] exp: -0.022007366313092042\n", "[64] exp: -0.022622920766789123\n", "[65] exp: -0.021856515255194026\n", "[66] exp: -0.022472069708891106\n", "[67] exp: -0.021856515255194026\n", "[68] exp: -0.022472069708891106\n", "[69] exp: -0.02154025585060333\n", "[70] exp: -0.02215581030430041\n", "[71] exp: -0.02277136475799749\n", "[72] exp: -0.02215581030430041\n", "[73] exp: -0.02154025585060333\n", "[74] exp: -0.02154025585060333\n", "[75] exp: -0.02154025585060333\n", "[76] exp: -0.020924701396906248\n", "[77] exp: -0.02027348570580591\n", "[78] exp: -0.020889040159502992\n", "[79] exp: -0.020889040159502992\n", "[80] exp: -0.021504594613200072\n", "[81] exp: -0.021504594613200072\n", "[82] exp: -0.020889040159502992\n", "[83] exp: -0.021504594613200072\n", "[84] exp: -0.022120149066897153\n", "[85] exp: -0.022120149066897153\n", "[86] exp: -0.021243892746641374\n", "[87] exp: -0.021243892746641374\n", "[88] exp: -0.021243892746641374\n", "[89] exp: -0.021243892746641374\n", "[90] exp: -0.022185495290800217\n", "[91] exp: -0.022801049744497297\n", "[92] exp: -0.023416604198194378\n", "[93] exp: -0.02403215865189146\n", "[94] exp: -0.024774427325995912\n", "[95] exp: -0.025389981779692993\n", "[96] exp: -0.024616313200662678\n", "[97] exp: -0.02523186765435976\n", "[98] exp: -0.02584742210805684\n", "[99] exp: -0.02584742210805684\n", "[100] exp: -0.02584742210805684\n", "[101] exp: -0.02646297656175392\n", "[102] exp: -0.027078531015451\n", "[103] exp: -0.02646297656175392\n", "[104] exp: -0.02738285481457356\n", "[105] exp: -0.02799840926827064\n", "[106] exp: -0.02861396372196772\n", "[107] exp: -0.0292295181756648\n", "[108] exp: -0.02861396372196772\n", "[109] exp: -0.0292295181756648\n", "[110] exp: -0.0292295181756648\n", "[111] exp: -0.028844127085841716\n", "[112] exp: -0.029459681539538797\n", "[113] exp: -0.030075235993235878\n", "[114] exp: -0.03069079044693296\n", "[115] exp: -0.03130634490063004\n", "[116] exp: -0.03192189935432713\n", "[117] exp: -0.03253745380802421\n", "[118] exp: -0.033153008261721295\n", "[119] exp: -0.033153008261721295\n", "[120] exp: -0.03256731390197995\n", "[121] exp: -0.031697881936676685\n", "[122] exp: -0.0326262076677459\n", "[123] exp: -0.0326262076677459\n", "[124] exp: -0.03324176212144298\n", "[125] exp: -0.03329003790769807\n", "[126] exp: -0.03329003790769807\n", "[127] exp: -0.033178062110633705\n", "[128] exp: -0.033178062110633705\n", "[129] exp: -0.03379361656433079\n", "[130] exp: -0.03469337345856942\n", "[131] exp: -0.0353089279122665\n", "[132] exp: -0.035274712648132055\n", "[133] exp: -0.03457582550242758\n", "[134] exp: -0.03519137995612467\n", "[135] exp: -0.03519137995612467\n", "[136] exp: -0.03548433926214502\n", "[137] exp: -0.0360998937158421\n", "[138] exp: -0.036715448169539186\n", "[139] exp: -0.03764651733823437\n", "[140] exp: -0.03799390757259266\n", "[141] exp: -0.03735273794352331\n", "[142] exp: -0.037968292397220396\n", "[143] exp: -0.03858384685091748\n", "[144] exp: -0.039199401304614565\n", "[145] exp: -0.03981495575831165\n", "[146] exp: -0.04043051021200873\n", "[147] exp: -0.04104606466570582\n", "[148] exp: -0.040898738600438696\n", "[149] exp: -0.04151429305413578\n", "[150] exp: -0.042389071112415314\n", "[151] exp: -0.0430046255661124\n", "[152] exp: -0.04362018001980948\n", "[153] exp: -0.044235734473506566\n", "[154] exp: -0.04485128892720365\n", "[155] exp: -0.045466843380900734\n", "[156] exp: -0.04632420363925691\n", "[157] exp: -0.046939758092954\n", "[158] exp: -0.046939758092954\n", "[159] exp: -0.046939758092954\n", "[160] exp: -0.04755531254665108\n", "[161] exp: -0.047945530209456085\n", "[162] exp: -0.04856108466315317\n", "[163] exp: -0.04917663911685025\n", "[164] exp: -0.04979219357054734\n", "[165] exp: -0.05040774802424442\n", "[166] exp: -0.05096822096932116\n", "[167] exp: -0.05096822096932116\n", "[168] exp: -0.05096822096932116\n", "[169] exp: -0.05096822096932116\n", "[170] exp: -0.05070501056763049\n", "[171] exp: -0.05028426867636907\n", "[172] exp: -0.04966871422267199\n", "[173] exp: -0.05028426867636907\n", "[174] exp: -0.049786289569978874\n", "[175] exp: -0.05040184402367596\n", "[176] exp: -0.05018326709830215\n", "[177] exp: -0.05079882155199923\n", "[178] exp: -0.05079882155199923\n", "[179] exp: -0.051414376005696316\n", "[180] exp: -0.0520299304593934\n", "[181] exp: -0.0520299304593934\n", "[182] exp: -0.05244870743096235\n", "[183] exp: -0.05332093018234459\n", "[184] exp: -0.05255129095555087\n", "[185] exp: -0.053406234553578354\n", "[186] exp: -0.053406234553578354\n", "[187] exp: -0.053406234553578354\n", "[188] exp: -0.053406234553578354\n", "[189] exp: -0.05402178900727544\n", "[190] exp: -0.05402178900727544\n", "[191] exp: -0.05463734346097252\n", "[192] exp: -0.05463734346097252\n", "[193] exp: -0.055252897914669606\n", "[194] exp: -0.05586845236836669\n", "[195] exp: -0.05586845236836669\n", "[196] exp: -0.05586845236836669\n", "[197] exp: -0.05586845236836669\n", "[198] exp: -0.056484006822063774\n", "[199] exp: -0.05709956127576086\n", "[200] exp: -0.05771511572945794\n", "[201] exp: -0.057257331940338795\n", "[202] exp: -0.05787288639403588\n", "[203] exp: -0.05848844084773296\n", "[204] exp: -0.05848844084773296\n", "[205] exp: -0.05848844084773296\n", "[206] exp: -0.05910399530143005\n", "[207] exp: -0.05971954975512713\n", "[208] exp: -0.060335104208824215\n", "[209] exp: -0.0609506586625213\n", "[210] exp: -0.061566213116218384\n", "[211] exp: -0.06218176756991547\n", "[212] exp: -0.061566213116218384\n", "[213] exp: -0.061566213116218384\n", "[214] exp: -0.061566213116218384\n", "[215] exp: -0.06218176756991547\n", "[216] exp: -0.06279732202361255\n", "[217] exp: -0.06341287647730963\n", "[218] exp: -0.06341287647730963\n", "[219] exp: -0.06320242027713613\n", "[220] exp: -0.06381797473083321\n", "[221] exp: -0.06381797473083321\n", "[222] exp: -0.06381797473083321\n", "[223] exp: -0.0644335291845303\n", "[224] exp: -0.0644335291845303\n", "[225] exp: -0.0644335291845303\n", "[226] exp: -0.06504908363822738\n", "[227] exp: -0.06566045904518757\n", "[228] exp: -0.06629484601530813\n", "[229] exp: -0.06691040046900522\n", "[230] exp: -0.0675259549227023\n", "[231] exp: -0.0675259549227023\n", "[232] exp: -0.0675259549227023\n", "[233] exp: -0.06814150937639939\n", "[234] exp: -0.0675259549227023\n", "[235] exp: -0.0675259549227023\n", "[236] exp: -0.06658499178537876\n", "[237] exp: -0.06720054623907584\n", "[238] exp: -0.06781610069277293\n", "[239] exp: -0.06843165514647001\n", "[240] exp: -0.06763770681196025\n", "[241] exp: -0.06763770681196025\n", "[242] exp: -0.06825326126565734\n", "[243] exp: -0.06763770681196025\n", "[244] exp: -0.06853694568164893\n", "[245] exp: -0.06915250013534602\n", "[246] exp: -0.0697680545890431\n", "[247] exp: -0.0697680545890431\n", "[248] exp: -0.07038360904274019\n", "[249] exp: -0.07099916349643727\n", "[250] exp: -0.07161471795013435\n", "[251] exp: -0.07161471795013435\n", "[252] exp: -0.07223027240383144\n", "[253] exp: -0.07284582685752852\n", "[254] exp: -0.07346138131122561\n", "[255] exp: -0.07284582685752852\n", "[256] exp: -0.07366915832301378\n", "[257] exp: -0.07428471277671087\n", "[258] exp: -0.07428471277671087\n", "[259] exp: -0.07490026723040795\n", "[260] exp: -0.07551582168410503\n", "[261] exp: -0.07645485198073491\n", "[262] exp: -0.077013721174219\n", "[263] exp: -0.07639816672052191\n", "[264] exp: -0.07565678898420304\n", "[265] exp: -0.07565678898420304\n", "[266] exp: -0.07565678898420304\n", "[267] exp: -0.07626129807519072\n", "[268] exp: -0.0768768525288878\n", "[269] exp: -0.0768768525288878\n", "[270] exp: -0.0768768525288878\n", "[271] exp: -0.07749240698258489\n", "[272] exp: -0.07831312700969287\n", "[273] exp: -0.07831312700969287\n", "[274] exp: -0.07892868146338995\n", "[275] exp: -0.07954423591708704\n", "[276] exp: -0.07954423591708704\n", "[277] exp: -0.08015979037078412\n", "[278] exp: -0.08059094536032106\n", "[279] exp: -0.08059094536032106\n", "[280] exp: -0.08120649981401815\n", "[281] exp: -0.08157819624890524\n", "[282] exp: -0.08219375070260232\n", "[283] exp: -0.0828093051562994\n", "[284] exp: -0.0828093051562994\n", "[285] exp: -0.08342485960999649\n", "[286] exp: -0.08404041406369357\n", "[287] exp: -0.08404041406369357\n", "[288] exp: -0.08465596851739066\n", "[289] exp: -0.08527152297108774\n", "[290] exp: -0.08527152297108774\n", "[291] exp: -0.08527152297108774\n", "[292] exp: -0.08527152297108774\n", "[293] exp: -0.08588707742478482\n", "[294] exp: -0.0867567128540497\n", "[295] exp: -0.0867567128540497\n", "[296] exp: -0.08769186862224454\n", "[297] exp: -0.08830742307594162\n", "[298] exp: -0.08762675616137959\n", "[299] exp: -0.08824231061507667\n", "[300] exp: -0.08885786506877376\n", "[301] exp: -0.08947341952247084\n", "[302] exp: -0.09008897397616793\n", "[303] exp: -0.08992489440956956\n", "[304] exp: -0.09054044886326665\n", "[305] exp: -0.09115600331696373\n", "[306] exp: -0.09115600331696373\n", "[307] exp: -0.09177155777066082\n", "[308] exp: -0.0923871122243579\n", "[309] exp: -0.09300266667805498\n", "[310] exp: -0.09300266667805498\n", "[311] exp: -0.09361822113175207\n", "[312] exp: -0.09362259542014313\n", "[313] exp: -0.0927733626660045\n", "[314] exp: -0.09338891711970158\n", "[315] exp: -0.09400447157339867\n", "[316] exp: -0.09400447157339867\n", "[317] exp: -0.09400447157339867\n", "[318] exp: -0.09462002602709575\n", "[319] exp: -0.09523558048079284\n", "[320] exp: -0.09466317228765633\n", "[321] exp: -0.09527872674135342\n", "[322] exp: -0.0958942811950505\n", "[323] exp: -0.0958942811950505\n", "[324] exp: -0.09650983564874759\n", "[325] exp: -0.09712539010244467\n", "[326] exp: -0.09712539010244467\n", "[327] exp: -0.09774094455614175\n", "[328] exp: -0.09835649900983884\n", "[329] exp: -0.09835649900983884\n", "[330] exp: -0.09897205346353592\n", "[331] exp: -0.09985418221730988\n", "[332] exp: -0.10046973667100696\n", "[333] exp: -0.09995536553146189\n", "[334] exp: -0.10028784636961895\n", "[335] exp: -0.10090340082331603\n", "[336] exp: -0.10090340082331603\n", "[337] exp: -0.10090340082331603\n", "[338] exp: -0.10151895527701311\n", "[339] exp: -0.10151895527701311\n", "[340] exp: -0.10156128221918276\n", "[341] exp: -0.10217683667287984\n", "[342] exp: -0.10217683667287984\n", "[343] exp: -0.10279239112657693\n", "[344] exp: -0.10340794558027401\n", "[345] exp: -0.10340794558027401\n", "[346] exp: -0.10340794558027401\n", "[347] exp: -0.1040235000339711\n", "[348] exp: -0.1040235000339711\n", "[349] exp: -0.1040235000339711\n", "[350] exp: -0.10372845672845833\n", "[351] exp: -0.10372845672845833\n", "[352] exp: -0.10449360452292311\n", "[353] exp: -0.10449360452292311\n", "[354] exp: -0.10365886584907227\n", "[355] exp: -0.10427442030276936\n", "[356] exp: -0.10350990238566947\n", "[357] exp: -0.10412545683936655\n", "[358] exp: -0.10474101129306364\n", "[359] exp: -0.10412545683936655\n", "[360] exp: -0.10474101129306364\n", "[361] exp: -0.10535656574676072\n", "[362] exp: -0.1059721202004578\n", "[363] exp: -0.1059721202004578\n", "[364] exp: -0.10658767465415489\n", "[365] exp: -0.10720322910785197\n", "[366] exp: -0.10781878356154906\n", "[367] exp: -0.10720322910785197\n", "[368] exp: -0.10781878356154906\n", "[369] exp: -0.10843433801524614\n", "[370] exp: -0.10937599813535294\n", "[371] exp: -0.1103166763434265\n", "[372] exp: -0.11038340107086211\n", "[373] exp: -0.11038340107086211\n", "[374] exp: -0.1109989555245592\n", "[375] exp: -0.11161450997825628\n", "[376] exp: -0.11223006443195337\n", "[377] exp: -0.11220202348282973\n", "[378] exp: -0.11281757793652682\n", "[379] exp: -0.11220202348282973\n", "[380] exp: -0.11281757793652682\n", "[381] exp: -0.11281757793652682\n", "[382] exp: -0.1134331323902239\n", "[383] exp: -0.11404868684392098\n", "[384] exp: -0.11466424129761807\n", "[385] exp: -0.11382570392058199\n", "[386] exp: -0.11444125837427907\n", "[387] exp: -0.11520844342214584\n", "[388] exp: -0.11520844342214584\n", "[389] exp: -0.11599975787962051\n", "[390] exp: -0.1166153123333176\n", "[391] exp: -0.1166153123333176\n", "[392] exp: -0.11754910433681005\n", "[393] exp: -0.11754910433681005\n", "[394] exp: -0.11816465879050714\n", "[395] exp: -0.11729727862856759\n", "[396] exp: -0.11791283308226468\n", "[397] exp: -0.11852838753596176\n", "[398] exp: -0.11851878407068736\n", "[399] exp: -0.11851878407068736\n", "[400] exp: -0.11913433852438444\n", "[401] exp: -0.12004965856631672\n", "[402] exp: -0.11942412855813303\n", "[403] exp: -0.11942412855813303\n", "[404] exp: -0.12003968301183011\n", "[405] exp: -0.12089213649740388\n", "[406] exp: -0.12150769095110096\n", "[407] exp: -0.12150769095110096\n", "[408] exp: -0.12089213649740388\n", "[409] exp: -0.12150769095110096\n", "[410] exp: -0.12212324540479805\n", "[411] exp: -0.12273879985849513\n", "[412] exp: -0.12335435431219222\n", "[413] exp: -0.12273879985849513\n", "[414] exp: -0.12273879985849513\n", "[415] exp: -0.12335435431219222\n", "[416] exp: -0.1239699087658893\n", "[417] exp: -0.12458546321958638\n", "[418] exp: -0.12550893711564767\n", "[419] exp: -0.12612449156934474\n", "[420] exp: -0.1267400460230418\n", "[421] exp: -0.12735560047673888\n", "[422] exp: -0.12801527002970922\n", "[423] exp: -0.1286308244834063\n", "[424] exp: -0.12801527002970922\n", "[425] exp: -0.12801527002970922\n", "[426] exp: -0.12866152456840213\n", "[427] exp: -0.1292770790220992\n", "[428] exp: -0.1283833689492389\n", "[429] exp: -0.12922282598498694\n", "[430] exp: -0.12922282598498694\n", "[431] exp: -0.12922282598498694\n", "[432] exp: -0.129838380438684\n", "[433] exp: -0.12915689756143836\n", "[434] exp: -0.12977245201513543\n", "[435] exp: -0.1303880064688325\n", "[436] exp: -0.13100356092252957\n", "[437] exp: -0.13161911537622664\n", "[438] exp: -0.13161911537622664\n", "[439] exp: -0.1322346698299237\n", "[440] exp: -0.1322346698299237\n", "[441] exp: -0.1322346698299237\n", "[442] exp: -0.13285022428362078\n", "[443] exp: -0.13240052676667394\n", "[444] exp: -0.133016081220371\n", "[445] exp: -0.13240052676667394\n", "[446] exp: -0.133016081220371\n", "[447] exp: -0.13363163567406808\n", "[448] exp: -0.13424719012776515\n", "[449] exp: -0.13424719012776515\n", "[450] exp: -0.13486274458146222\n", "[451] exp: -0.1354782990351593\n", "[452] exp: -0.1355789395032875\n", "[453] exp: -0.1355789395032875\n", "[454] exp: -0.13619449395698457\n", "[455] exp: -0.13681004841068165\n", "[456] exp: -0.13681004841068165\n", "[457] exp: -0.13742560286437872\n", "[458] exp: -0.13804115731807579\n", "[459] exp: -0.13865671177177286\n", "[460] exp: -0.13804115731807579\n", "[461] exp: -0.13804115731807579\n", "[462] exp: -0.13804115731807579\n", "[463] exp: -0.13836275404663967\n", "[464] exp: -0.13897830850033674\n", "[465] exp: -0.13836275404663967\n", "[466] exp: -0.13906106231693482\n", "[467] exp: -0.13906106231693482\n", "[468] exp: -0.13999196215156873\n", "[469] exp: -0.13937640769787166\n", "[470] exp: -0.13999196215156873\n", "[471] exp: -0.1406075166052658\n", "[472] exp: -0.1406075166052658\n", "[473] exp: -0.1406075166052658\n", "[474] exp: -0.1406075166052658\n", "[475] exp: -0.14122307105896287\n", "[476] exp: -0.14183862551265994\n", "[477] exp: -0.14183862551265994\n", "[478] exp: -0.142454179966357\n", "[479] exp: -0.142454179966357\n", "[480] exp: -0.14306973442005408\n", "[481] exp: -0.14368528887375115\n", "[482] exp: -0.14430084332744822\n", "[483] exp: -0.14430084332744822\n", "[484] exp: -0.1451826007693763\n", "[485] exp: -0.14579815522307338\n", "[486] exp: -0.14579815522307338\n", "[487] exp: -0.14641370967677045\n", "[488] exp: -0.14702926413046752\n", "[489] exp: -0.1476448185841646\n", "[490] exp: -0.1476448185841646\n", "[491] exp: -0.14828957592651873\n", "[492] exp: -0.1489051303802158\n", "[493] exp: -0.1489051303802158\n", "[494] exp: -0.14952068483391287\n", "[495] exp: -0.15013623928760994\n", "[496] exp: -0.150751793741307\n", "[497] exp: -0.15136734819500408\n", "[498] exp: -0.15136734819500408\n", "[499] exp: -0.15198290264870115\n", "[500] exp: -0.15259845710239822\n", "[501] exp: -0.15342576279459505\n", "[502] exp: -0.1527157862429297\n", "[503] exp: -0.15333134069662677\n", "[504] exp: -0.15400963967833595\n", "[505] exp: -0.15462519413203302\n", "[506] exp: -0.1552407485857301\n", "[507] exp: -0.15609221841700868\n", "[508] exp: -0.15609221841700868\n", "[509] exp: -0.15670777287070575\n", "[510] exp: -0.15756360783863435\n", "[511] exp: -0.15817916229233142\n", "[512] exp: -0.1587947167460285\n", "[513] exp: -0.15941027119972556\n", "[514] exp: -0.1603515042602213\n", "[515] exp: -0.16096705871391837\n", "[516] exp: -0.16096705871391837\n", "[517] exp: -0.16096705871391837\n", "[518] exp: -0.16096705871391837\n", "[519] exp: -0.16096705871391837\n", "[520] exp: -0.16158261316761544\n", "[521] exp: -0.1621981676213125\n", "[522] exp: -0.16281372207500958\n", "[523] exp: -0.16373090678339808\n", "[524] exp: -0.16283280712951734\n", "[525] exp: -0.1634483615832144\n", "[526] exp: -0.16283280712951734\n", "[527] exp: -0.1634483615832144\n", "[528] exp: -0.16406391603691148\n", "[529] exp: -0.16467947049060855\n", "[530] exp: -0.1644017050894879\n", "[531] exp: -0.1644017050894879\n", "[532] exp: -0.1644017050894879\n", "[533] exp: -0.16377946085970288\n", "[534] exp: -0.16439501531339995\n", "[535] exp: -0.16377946085970288\n", "[536] exp: -0.16439501531339995\n", "[537] exp: -0.16439501531339995\n", "[538] exp: -0.16501056976709702\n", "[539] exp: -0.1656261242207941\n", "[540] exp: -0.16624167867449116\n", "[541] exp: -0.16685723312818823\n", "[542] exp: -0.1674727875818853\n", "[543] exp: -0.1674727875818853\n", "[544] exp: -0.16808834203558237\n", "[545] exp: -0.16870389648927944\n", "[546] exp: -0.1693194509429765\n", "[547] exp: -0.16993500539667358\n", "[548] exp: -0.16993500539667358\n", "[549] exp: -0.17055055985037065\n", "[550] exp: -0.17116611430406772\n", "[551] exp: -0.17144413665008618\n", "[552] exp: -0.17205969110378325\n", "[553] exp: -0.17267524555748032\n", "[554] exp: -0.1732908000111774\n", "[555] exp: -0.17340554640099856\n", "[556] exp: -0.17402110085469563\n", "[557] exp: -0.17364917907930433\n", "[558] exp: -0.17364917907930433\n", "[559] exp: -0.17270769519848728\n", "[560] exp: -0.17332324965218435\n", "[561] exp: -0.17393880410588142\n", "[562] exp: -0.1745543585595785\n", "[563] exp: -0.1745543585595785\n", "[564] exp: -0.17516991301327556\n", "[565] exp: -0.17516991301327556\n", "[566] exp: -0.17578546746697263\n", "[567] exp: -0.1764010219206697\n", "[568] exp: -0.17701657637436677\n", "[569] exp: -0.17767756727117226\n", "[570] exp: -0.17829312172486933\n", "[571] exp: -0.1789086761785664\n", "[572] exp: -0.17952423063226347\n", "[573] exp: -0.18013978508596054\n", "[574] exp: -0.1804705539298588\n", "[575] exp: -0.17973981678169074\n", "[576] exp: -0.17973981678169074\n", "[577] exp: -0.1803553712353878\n", "[578] exp: -0.18097092568908488\n", "[579] exp: -0.1803553712353878\n", "[580] exp: -0.1803553712353878\n", "[581] exp: -0.1803553712353878\n", "[582] exp: -0.18097092568908488\n", "[583] exp: -0.18097092568908488\n", "[584] exp: -0.18158648014278195\n", "[585] exp: -0.18158648014278195\n", "[586] exp: -0.18097092568908488\n", "[587] exp: -0.18158648014278195\n", "[588] exp: -0.18097092568908488\n", "[589] exp: -0.18097092568908488\n", "[590] exp: -0.18158648014278195\n", "[591] exp: -0.18220203459647902\n", "[592] exp: -0.1828175890501761\n", "[593] exp: -0.1828175890501761\n", "[594] exp: -0.1820724559922206\n", "[595] exp: -0.1820724559922206\n", "[596] exp: -0.18268801044591768\n", "[597] exp: -0.18330356489961475\n", "[598] exp: -0.18391911935331182\n", "[599] exp: -0.18391911935331182\n", "[600] exp: -0.18330356489961475\n", "[601] exp: -0.18391911935331182\n", "[602] exp: -0.1845346738070089\n", "[603] exp: -0.18515022826070596\n", "[604] exp: -0.18515022826070596\n", "[605] exp: -0.18515022826070596\n", "[606] exp: -0.18515022826070596\n", "[607] exp: -0.18606380694628738\n", "[608] exp: -0.18655856768528278\n", "[609] exp: -0.18655856768528278\n", "[610] exp: -0.18743839411350321\n", "[611] exp: -0.18819919063543192\n", "[612] exp: -0.188814745089129\n", "[613] exp: -0.18943029954282606\n", "[614] exp: -0.18943029954282606\n", "[615] exp: -0.19004585399652313\n", "[616] exp: -0.19004585399652313\n", "[617] exp: -0.19097182613698546\n", "[618] exp: -0.19073563167538965\n", "[619] exp: -0.19135118612908672\n", "[620] exp: -0.19150988368625607\n", "[621] exp: -0.19212543813995314\n", "[622] exp: -0.19249690955466886\n", "[623] exp: -0.19212397847611082\n", "[624] exp: -0.1927395329298079\n", "[625] exp: -0.1927395329298079\n", "[626] exp: -0.19335508738350496\n", "[627] exp: -0.19335508738350496\n", "[628] exp: -0.19358784467544485\n", "[629] exp: -0.19420339912914192\n", "[630] exp: -0.19420339912914192\n", "[631] exp: -0.194818953582839\n", "[632] exp: -0.19543450803653606\n", "[633] exp: -0.19543450803653606\n", "[634] exp: -0.19605006249023313\n", "[635] exp: -0.19605006249023313\n", "[636] exp: -0.19605006249023313\n", "[637] exp: -0.19659884679466627\n", "[638] exp: -0.19721440124836334\n", "[639] exp: -0.1978299557020604\n", "[640] exp: -0.19844551015575748\n", "[641] exp: -0.19906106460945455\n", "[642] exp: -0.19967661906315162\n", "[643] exp: -0.2002921735168487\n", "[644] exp: -0.20090772797054576\n", "[645] exp: -0.20152328242424283\n", "[646] exp: -0.2021388368779399\n", "[647] exp: -0.2021388368779399\n", "[648] exp: -0.2021388368779399\n", "[649] exp: -0.2021388368779399\n", "[650] exp: -0.2021388368779399\n", "[651] exp: -0.2021388368779399\n", "[652] exp: -0.2021388368779399\n", "[653] exp: -0.20275439133163697\n", "[654] exp: -0.20336994578533404\n", "[655] exp: -0.20398550023903111\n", "[656] exp: -0.20398550023903111\n", "[657] exp: -0.20460105469272818\n", "[658] exp: -0.20521660914642526\n", "[659] exp: -0.20608586916399166\n", "[660] exp: -0.20670142361768873\n", "[661] exp: -0.2073169780713858\n", "[662] exp: -0.20670142361768873\n", "[663] exp: -0.2074788621088741\n", "[664] exp: -0.20809441656257116\n", "[665] exp: -0.20870997101626823\n", "[666] exp: -0.2093255254699653\n", "[667] exp: -0.2093255254699653\n", "[668] exp: -0.2093255254699653\n", "[669] exp: -0.20994107992366237\n", "[670] exp: -0.21055663437735944\n", "[671] exp: -0.2111721888310565\n", "[672] exp: -0.21196939145049798\n", "[673] exp: -0.21258494590419505\n", "[674] exp: -0.21320050035789212\n", "[675] exp: -0.21383806905960145\n", "[676] exp: -0.21445362351329852\n", "[677] exp: -0.21383806905960145\n", "[678] exp: -0.21290012410261003\n", "[679] exp: -0.2135156785563071\n", "[680] exp: -0.2135156785563071\n", "[681] exp: -0.21413123301000417\n", "[682] exp: -0.2135156785563071\n", "[683] exp: -0.21413123301000417\n", "[684] exp: -0.21413123301000417\n", "[685] exp: -0.21474678746370124\n", "[686] exp: -0.21474678746370124\n", "[687] exp: -0.21474678746370124\n", "[688] exp: -0.2153623419173983\n", "[689] exp: -0.21597789637109538\n", "[690] exp: -0.2150429143742402\n", "[691] exp: -0.21565846882793727\n", "[692] exp: -0.21551390800633224\n", "[693] exp: -0.21551390800633224\n", "[694] exp: -0.21551390800633224\n", "[695] exp: -0.21551390800633224\n", "[696] exp: -0.21612946246002931\n", "[697] exp: -0.21551390800633224\n", "[698] exp: -0.21612946246002931\n", "[699] exp: -0.21612946246002931\n", "[700] exp: -0.21674501691372638\n", "[701] exp: -0.21674501691372638\n", "[702] exp: -0.21763149675266333\n", "[703] exp: -0.21763149675266333\n", "[704] exp: -0.21844270576049665\n", "[705] exp: -0.21782715130679958\n", "[706] exp: -0.21844270576049665\n", "[707] exp: -0.21905826021419372\n", "[708] exp: -0.21905826021419372\n", "[709] exp: -0.2196738146678908\n", "[710] exp: -0.22028936912158786\n", "[711] exp: -0.22090492357528493\n", "[712] exp: -0.22090492357528493\n", "[713] exp: -0.22182850664546006\n", "[714] exp: -0.2214704732413619\n", "[715] exp: -0.22208602769505897\n", "[716] exp: -0.22270158214875604\n", "[717] exp: -0.22331713660245311\n", "[718] exp: -0.22393269105615018\n", "[719] exp: -0.22454824550984726\n", "[720] exp: -0.22516379996354433\n", "[721] exp: -0.22471567931191222\n", "[722] exp: -0.2253312337656093\n", "[723] exp: -0.22594678821930636\n", "[724] exp: -0.22656234267300343\n", "[725] exp: -0.22656234267300343\n", "[726] exp: -0.22563124834934478\n", "[727] exp: -0.22624680280304185\n", "[728] exp: -0.22695221209638056\n", "[729] exp: -0.22756776655007763\n", "[730] exp: -0.2281833210037747\n", "[731] exp: -0.22879887545747177\n", "[732] exp: -0.22791825864325793\n", "[733] exp: -0.22791825864325793\n", "[734] exp: -0.22791825864325793\n", "[735] exp: -0.228533813096955\n", "[736] exp: -0.22914936755065207\n", "[737] exp: -0.22976492200434914\n", "[738] exp: -0.22976492200434914\n", "[739] exp: -0.23006736939645864\n", "[740] exp: -0.23006736939645864\n", "[741] exp: -0.2306829238501557\n", "[742] exp: -0.23129847830385278\n", "[743] exp: -0.23191403275754985\n", "[744] exp: -0.23269331572343316\n", "[745] exp: -0.23229780870770897\n", "[746] exp: -0.23291336316140604\n", "[747] exp: -0.2335289176151031\n", "[748] exp: -0.2335289176151031\n", "[749] exp: -0.23414447206880018\n", "[750] exp: -0.23476002652249725\n", "[751] exp: -0.23537558097619432\n", "[752] exp: -0.2359911354298914\n", "[753] exp: -0.2366816862279394\n", "[754] exp: -0.23729724068163646\n", "[755] exp: -0.2366816862279394\n", "[756] exp: -0.23729724068163646\n", "[757] exp: -0.2366816862279394\n", "[758] exp: -0.23729724068163646\n", "[759] exp: -0.23751966337302066\n", "[760] exp: -0.23813521782671773\n", "[761] exp: -0.23813521782671773\n", "[762] exp: -0.23751966337302066\n", "[763] exp: -0.23748434234037025\n", "[764] exp: -0.23809989679406732\n", "[765] exp: -0.2387154512477644\n", "[766] exp: -0.23933100570146146\n", "[767] exp: -0.23994656015515853\n", "[768] exp: -0.2405621146088556\n", "[769] exp: -0.24117766906255267\n", "[770] exp: -0.24179322351624974\n", "[771] exp: -0.2424087779699468\n", "[772] exp: -0.24256286025472576\n", "[773] exp: -0.24317841470842283\n", "[774] exp: -0.2437939691621199\n", "[775] exp: -0.24388015971144672\n", "[776] exp: -0.2430025795504418\n", "[777] exp: -0.24361813400413887\n", "[778] exp: -0.24423368845783594\n", "[779] exp: -0.2442418955889244\n", "[780] exp: -0.24485745004262147\n", "[781] exp: -0.24547300449631854\n", "[782] exp: -0.2456807075066957\n", "[783] exp: -0.24629626196039278\n", "[784] exp: -0.24713400058278212\n", "[785] exp: -0.24651844612908505\n", "[786] exp: -0.24651844612908505\n", "[787] exp: -0.24713400058278212\n", "[788] exp: -0.2477495550364792\n", "[789] exp: -0.24836510949017626\n", "[790] exp: -0.24836510949017626\n", "[791] exp: -0.24836510949017626\n", "[792] exp: -0.24898066394387333\n", "[793] exp: -0.2495962183975704\n", "[794] exp: -0.2495962183975704\n", "[795] exp: -0.25051117355932184\n", "[796] exp: -0.25112672801301894\n", "[797] exp: -0.25112672801301894\n", "[798] exp: -0.25174228246671604\n", "[799] exp: -0.25235783692041314\n", "[800] exp: -0.25297339137411023\n", "[801] exp: -0.25358894582780733\n", "[802] exp: -0.25420450028150443\n", "[803] exp: -0.25482005473520153\n", "[804] exp: -0.2554356091888986\n", "[805] exp: -0.2554356091888986\n", "[806] exp: -0.2560511636425957\n", "[807] exp: -0.2566667180962928\n", "[808] exp: -0.2572822725499899\n", "[809] exp: -0.257897827003687\n", "[810] exp: -0.2585133814573841\n", "[811] exp: -0.2591289359110812\n", "[812] exp: -0.2597444903647783\n", "[813] exp: -0.2603600448184754\n", "[814] exp: -0.2609755992721725\n", "[815] exp: -0.2615911537258696\n", "[816] exp: -0.26194188750198566\n", "[817] exp: -0.26194188750198566\n", "[818] exp: -0.26255744195568276\n", "[819] exp: -0.26317299640937986\n", "[820] exp: -0.26255744195568276\n", "[821] exp: -0.26255744195568276\n", "[822] exp: -0.26255744195568276\n", "[823] exp: -0.26317299640937986\n", "[824] exp: -0.26378855086307695\n", "[825] exp: -0.26440410531677405\n", "[826] exp: -0.26440410531677405\n", "[827] exp: -0.26501965977047115\n", "[828] exp: -0.2658114564052007\n", "[829] exp: -0.2658114564052007\n", "[830] exp: -0.26654768954301\n", "[831] exp: -0.26654768954301\n", "[832] exp: -0.2657089792429236\n", "[833] exp: -0.2663245336966207\n", "[834] exp: -0.2663245336966207\n", "[835] exp: -0.2669400881503178\n", "[836] exp: -0.2669400881503178\n", "[837] exp: -0.2675556426040149\n", "[838] exp: -0.268171197057712\n", "[839] exp: -0.26878675151140907\n", "[840] exp: -0.268171197057712\n", "[841] exp: -0.268171197057712\n", "[842] exp: -0.268171197057712\n", "[843] exp: -0.26878675151140907\n", "[844] exp: -0.26940230596510617\n", "[845] exp: -0.27001786041880327\n", "[846] exp: -0.26940230596510617\n", "[847] exp: -0.2696050634297452\n", "[848] exp: -0.26894336376939737\n", "[849] exp: -0.26955891822309447\n", "[850] exp: -0.26955891822309447\n", "[851] exp: -0.2700922968507422\n", "[852] exp: -0.2700922968507422\n", "[853] exp: -0.2700922968507422\n", "[854] exp: -0.2707078513044393\n", "[855] exp: -0.2713234057581364\n", "[856] exp: -0.2713234057581364\n", "[857] exp: -0.2713234057581364\n", "[858] exp: -0.2719389602118335\n", "[859] exp: -0.2723312986160437\n", "[860] exp: -0.2729468530697408\n", "[861] exp: -0.2735624075234379\n", "[862] exp: -0.274177961977135\n", "[863] exp: -0.274177961977135\n", "[864] exp: -0.274177961977135\n", "[865] exp: -0.2747935164308321\n", "[866] exp: -0.2754090708845292\n", "[867] exp: -0.2760246253382263\n", "[868] exp: -0.2766401797919234\n", "[869] exp: -0.2772557342456205\n", "[870] exp: -0.2778712886993176\n", "[871] exp: -0.2784868431530147\n", "[872] exp: -0.2791023976067118\n", "[873] exp: -0.2784868431530147\n", "[874] exp: -0.2784868431530147\n", "[875] exp: -0.2791023976067118\n", "[876] exp: -0.2782980485067252\n", "[877] exp: -0.27735874637169267\n", "[878] exp: -0.27797430082538976\n", "[879] exp: -0.27858985527908686\n", "[880] exp: -0.27920540973278396\n", "[881] exp: -0.27982096418648106\n", "[882] exp: -0.27982096418648106\n", "[883] exp: -0.27982096418648106\n", "[884] exp: -0.28043651864017816\n", "[885] exp: -0.28043651864017816\n", "[886] exp: -0.28105207309387525\n", "[887] exp: -0.28105207309387525\n", "[888] exp: -0.28166762754757235\n", "[889] exp: -0.28228318200126945\n", "[890] exp: -0.28289873645496655\n", "[891] exp: -0.2825211540269534\n", "[892] exp: -0.2831367084806505\n", "[893] exp: -0.2831367084806505\n", "[894] exp: -0.2837522629343476\n", "[895] exp: -0.2843678173880447\n", "[896] exp: -0.2837522629343476\n", "[897] exp: -0.2843347405672988\n", "[898] exp: -0.2843347405672988\n", "[899] exp: -0.2845791570436383\n", "[900] exp: -0.2845791570436383\n", "[901] exp: -0.2839636025899412\n", "[902] exp: -0.2845791570436383\n", "[903] exp: -0.2839636025899412\n", "[904] exp: -0.2833480481362441\n", "[905] exp: -0.2839636025899412\n", "[906] exp: -0.2845791570436383\n", "[907] exp: -0.2851947114973354\n", "[908] exp: -0.28543574532739174\n", "[909] exp: -0.28605129978108884\n", "[910] exp: -0.28605129978108884\n", "[911] exp: -0.28529738883815065\n", "[912] exp: -0.28529738883815065\n", "[913] exp: -0.2859254146897928\n", "[914] exp: -0.2868482797677258\n", "[915] exp: -0.2874638342214229\n", "[916] exp: -0.28807938867512\n", "[917] exp: -0.28807938867512\n", "[918] exp: -0.2886949431288171\n", "[919] exp: -0.28960982734083196\n", "[920] exp: -0.29022538179452906\n", "[921] exp: -0.29084093624822616\n", "[922] exp: -0.29145649070192325\n", "[923] exp: -0.29207204515562035\n", "[924] exp: -0.29268759960931745\n", "[925] exp: -0.29268759960931745\n", "[926] exp: -0.29330315406301455\n", "[927] exp: -0.29391870851671165\n", "[928] exp: -0.29391870851671165\n", "[929] exp: -0.29453426297040874\n", "[930] exp: -0.29545259668810003\n", "[931] exp: -0.29545259668810003\n", "[932] exp: -0.29483704223440294\n", "[933] exp: -0.29545259668810003\n", "[934] exp: -0.29606815114179713\n", "[935] exp: -0.29606815114179713\n", "[936] exp: -0.29668370559549423\n", "[937] exp: -0.2972992600491913\n", "[938] exp: -0.2979148145028884\n", "[939] exp: -0.2979148145028884\n", "[940] exp: -0.2979148145028884\n", "[941] exp: -0.2979148145028884\n", "[942] exp: -0.2985303689565855\n", "[943] exp: -0.2991459234102826\n", "[944] exp: -0.2991459234102826\n", "[945] exp: -0.2991459234102826\n", "[946] exp: -0.2997614778639797\n", "[947] exp: -0.2997614778639797\n", "[948] exp: -0.2997614778639797\n", "[949] exp: -0.3003770323176768\n", "[950] exp: -0.3013107890652462\n", "[951] exp: -0.3013107890652462\n", "[952] exp: -0.3004164880131131\n", "[953] exp: -0.299800933559416\n", "[954] exp: -0.30024286071658635\n", "[955] exp: -0.29962730626288925\n", "[956] exp: -0.30024286071658635\n", "[957] exp: -0.3002399965717314\n", "[958] exp: -0.3008555510254285\n", "[959] exp: -0.3014711054791256\n", "[960] exp: -0.3008555510254285\n", "[961] exp: -0.3014711054791256\n", "[962] exp: -0.3014711054791256\n", "[963] exp: -0.3014711054791256\n", "[964] exp: -0.3020866599328227\n", "[965] exp: -0.3020866599328227\n", "[966] exp: -0.3027022143865198\n", "[967] exp: -0.3033177688402169\n", "[968] exp: -0.303933323293914\n", "[969] exp: -0.3045488777476111\n", "[970] exp: -0.3051644322013082\n", "[971] exp: -0.3051644322013082\n", "[972] exp: -0.3051644322013082\n", "[973] exp: -0.30424607952190996\n", "[974] exp: -0.3036183112721912\n", "[975] exp: -0.3042338657258883\n", "[976] exp: -0.3048494201795854\n", "[977] exp: -0.3054649746332825\n", "[978] exp: -0.30453069264814825\n", "[979] exp: -0.30514624710184535\n", "[980] exp: -0.30433271597198613\n", "[981] exp: -0.30512125684171765\n", "[982] exp: -0.30512125684171765\n", "[983] exp: -0.30450570238802055\n", "[984] exp: -0.30476178907673923\n", "[985] exp: -0.30537734353043633\n", "[986] exp: -0.3059928979841334\n", "[987] exp: -0.3059928979841334\n", "[988] exp: -0.3066084524378305\n", "[989] exp: -0.3072240068915276\n", "[990] exp: -0.3072240068915276\n", "[991] exp: -0.3072240068915276\n", "[992] exp: -0.3076771002911508\n", "[993] exp: -0.3076771002911508\n", "[994] exp: -0.3082926547448479\n", "[995] exp: -0.3082926547448479\n", "[996] exp: -0.308908209198545\n", "[997] exp: -0.308908209198545\n", "[998] exp: -0.3095237636522421\n", "[999] exp: -0.3101393181059392\n" ] } ], "source": [ "from qulacs import QuantumState, Observable, GeneralQuantumOperator\n", "from qulacs.gate import NoisyEvolution, NoisyEvolution_fast, H\n", "\n", "n = 2\n", "observable = Observable(n)\n", "observable.add_operator(1., \"X 0\")\n", "\n", "# create hamiltonian and collapse operator\n", "hamiltonian = Observable(n)\n", "hamiltonian.add_operator(1., \"Z 0 Z 1\")\n", "\n", "decay_rate_z = 0.2\n", "decay_rate_p = 0.6\n", "decay_rate_m = 0.1\n", "\n", "# interacting operator\n", "c_ops = [GeneralQuantumOperator(n) for _ in range(3*n)]\n", "c_ops[0].add_operator(decay_rate_z, \"Z 0\")\n", "c_ops[1].add_operator(decay_rate_z, \"Z 1\")\n", "c_ops[2].add_operator(decay_rate_p/2, \"X 0\")\n", "c_ops[2].add_operator(decay_rate_p/2*1j, \"Y 0\")\n", "c_ops[3].add_operator(decay_rate_p/2, \"X 1\")\n", "c_ops[3].add_operator(decay_rate_p/2*1j, \"Y 1\")\n", "c_ops[4].add_operator(decay_rate_m/2, \"X 0\")\n", "c_ops[4].add_operator(-decay_rate_m/2*1j, \"Y 0\")\n", "c_ops[5].add_operator(decay_rate_m/2, \"X 1\")\n", "c_ops[5].add_operator(-decay_rate_m/2*1j, \"Y 1\")\n", "\n", "time = 2.\n", "gate = NoisyEvolution_fast(hamiltonian, c_ops, time)\n", "#dt = .1\n", "#gate = NoisyEvolution(hamiltonian, c_ops, time, dt)\n", "\n", "exp = 0.\n", "n_samples = 1000\n", "state = QuantumState(n)\n", "for k in range(n_samples):\n", " state.set_zero_state()\n", " H(0).update_quantum_state(state)\n", " H(1).update_quantum_state(state)\n", " gate.update_quantum_state(state)\n", " exp += observable.get_expectation_value(state) / n_samples\n", " print(f\"[{k}] exp: {exp}\")\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### CPTP mapping\n", "`CPTP` is created by giving a list of Claus operators that satisfy the completeness." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "[0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "[0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "[0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n", "[1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "[0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "[0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "[0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n", "[0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n" ] } ], "source": [ "from qulacs.gate import merge,CPTP, P0,P1\n", "\n", "gate00 = merge(P0(0),P0(1))\n", "gate01 = merge(P0(0),P1(1))\n", "gate10 = merge(P1(0),P0(1))\n", "gate11 = merge(P1(0),P1(1))\n", "\n", "gate_list = [gate00, gate01, gate10, gate11]\n", "gate = CPTP(gate_list)\n", "\n", "from qulacs import QuantumState\n", "from qulacs.gate import H,merge\n", "state = QuantumState(2)\n", "for _ in range(10):\n", " state.set_zero_state()\n", " merge(H(0),H(1)).update_quantum_state(state)\n", " gate.update_quantum_state(state)\n", " print(state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "The `AmplitudeDampingNoise` gate is defined as CPTP-map." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "text/plain": [ " *** gate info *** \n", " * gate name : Generic gate\n", " * target : \n", " * control : \n", " * Pauli : no\n", " * Clifford : no\n", " * Gaussian : no\n", " * Parametric: no\n", " * Diagonal : yes" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from qulacs.gate import AmplitudeDampingNoise\n", "target = 0\n", "damping_rate = 0.1\n", "AmplitudeDampingNoise(target, damping_rate) \n", "#K_0: [[1,0],[0,sqrt(1-p)]], K_1: [[0,sqrt(p)], [0,0]]\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Instrument\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "1 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "2 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "3 10 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n", "4 00 [1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "5 01 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "6 11 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n", "7 11 [0.+0.j 0.+0.j 0.+0.j 1.+0.j]\n", "8 00 [1.+0.j 0.+0.j 0.+0.j 0.+0.j]\n", "9 10 [0.+0.j 0.+0.j 1.+0.j 0.+0.j]\n" ] } ], "source": [ "from qulacs import QuantumState\n", "from qulacs.gate import merge,Instrument, P0,P1\n", "\n", "gate00 = merge(P0(0),P0(1))\n", "gate01 = merge(P1(0),P0(1))\n", "gate10 = merge(P0(0),P1(1))\n", "gate11 = merge(P1(0),P1(1))\n", "\n", "gate_list = [gate00, gate01, gate10, gate11]\n", "classical_pos = 0\n", "gate = Instrument(gate_list, classical_pos)\n", "\n", "from qulacs import QuantumState\n", "from qulacs.gate import H,merge\n", "state = QuantumState(2)\n", "for index in range(10):\n", " state.set_zero_state()\n", " merge(H(0),H(1)).update_quantum_state(state)\n", " gate.update_quantum_state(state)\n", " result = state.get_classical_value(classical_pos)\n", " print(index, format(result,\"b\").zfill(2), state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "Note that `Measurement` gate is defined as Instrument." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qulacs.gate import Measurement\n", "target = 0\n", "classical_pos = 0\n", "gate = Measurement(target, classical_pos)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### ProbabilisticInstrument\n", "In addition to the `Probabilistic` function, it is a function that can get the index of the operated gate. If the sum of the distribution is less than 1, or for some other reason no gate has acted, the number of elements in `gate_list` is saved in `classical_address`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2 [0.70710678+0.j 0.70710678+0.j 0. +0.j 0. +0.j]\n", "0 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "1 [0.-0.j 0.+1.j 0.-0.j 0.+0.j]\n", "1 [0.-0.j 0.+1.j 0.-0.j 0.+0.j]\n", "2 [0.70710678+0.j 0.70710678+0.j 0. +0.j 0. +0.j]\n", "0 [0.+0.j 1.+0.j 0.+0.j 0.+0.j]\n", "1 [0.-0.j 0.+1.j 0.-0.j 0.+0.j]\n", "1 [0.-0.j 0.+1.j 0.-0.j 0.+0.j]\n", "2 [0.70710678+0.j 0.70710678+0.j 0. +0.j 0. +0.j]\n", "2 [0.70710678+0.j 0.70710678+0.j 0. +0.j 0. +0.j]\n" ] } ], "source": [ "from qulacs import QuantumState\n", "from qulacs.gate import X, Y, H, ProbabilisticInstrument\n", "n = 2\n", "state = QuantumState(n)\n", "index = 0\n", "x_gate = X(index)\n", "y_gate = Y(index)\n", "h_gate = H(index)\n", "distribution = [0.25, 0.25, 0.25]\n", "gate_list = [x_gate, y_gate, h_gate]\n", "classical_address = 0\n", "for _ in range(10):\n", " state = QuantumState(n)\n", " probabilistic_instrument_gate = ProbabilisticInstrument(distribution, gate_list, classical_address)\n", " probabilistic_instrument_gate.update_quantum_state(state)\n", " result = state.get_classical_value(classical_address)\n", " print(result, state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Adaptive operation\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "func is called! content is [0]\n", "[1.+0.j 0.+0.j]\n", "func is called! content is [1]\n", "[0.+0.j 1.+0.j]\n" ] } ], "source": [ "from qulacs.gate import Adaptive, X\n", "\n", "def func(list):\n", " print(\"func is called! content is \",list)\n", " return list[0]==1\n", "\n", "\n", "gate = Adaptive(X(0), func)\n", "\n", "state = QuantumState(1)\n", "state.set_zero_state()\n", "\n", "# func returns False, so X does not operate\n", "state.set_classical_value(0,0)\n", "gate.update_quantum_state(state)\n", "print(state.get_vector())\n", "\n", "# func returns True, so X operates\n", "state.set_classical_value(0,1)\n", "gate.update_quantum_state(state)\n", "print(state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Operator\n", "\n", "### Pauli operator\n", "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.\n", "\n", "#### Create Pauli operator and obtain state" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(0.1+0j) X0 Y1 Z3 Y3\n" ] } ], "source": [ "from qulacs import PauliOperator\n", "# Create Pauli Operator from pauli_string\n", "coef = 0.1\n", "s = \"X 0 Y 1 Z 3\"\n", "pauli = PauliOperator(s, coef)\n", "# Or, from index_list and type_list\n", "coef = 0.1\n", "index_list = [0, 1, 3]\n", "type_list = \"XYZ\"\n", "pauli = PauliOperator(index_list, type_list, coef)\n", "\n", "# Added pauli symbol later\n", "pauli.add_single_Pauli(3, 2)\n", "\n", "# Get the subscript of each pauli symbol\n", "index_list = pauli.get_index_list()\n", "\n", "# Get pauli symbols (I,X,Y,Z -> 0,1,2,3)\n", "pauli_id_list = pauli.get_pauli_id_list()\n", "\n", "# Get pauli coefficient\n", "coef = pauli.get_coef()\n", "\n", "# Create a copy of pauli operator\n", "another_pauli = pauli.copy()\n", "\n", "s = [\"I\",\"X\",\"Y\",\"Z\"]\n", "pauli_str = [s[i] for i in pauli_id_list]\n", "terms_str = [item[0]+str(item[1]) for item in zip(pauli_str,index_list)]\n", "full_str = str(coef) + \" \" + \" \".join(terms_str)\n", "print(full_str)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Expected value of Pauli operator\n", "You can evaluate the expected value and transition moment of the Pauli operator for one state." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "expect (0.6132028798856664+0j)\n", "transition (0.5279713648817308-0.6040063466314933j)\n" ] } ], "source": [ "from qulacs import PauliOperator, QuantumState\n", "\n", "n = 5\n", "coef = 2.0\n", "Pauli_string = \"X 0 X 1 Y 2 Z 4\"\n", "pauli = PauliOperator(Pauli_string,coef)\n", "\n", "# Calculate expectation value \n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "value = pauli.get_expectation_value(state)\n", "print(\"expect\", value)\n", "\n", "# Calculate transition moment \n", "# The first arguments comes to the bra side\n", "bra = QuantumState(n)\n", "bra.set_Haar_random_state()\n", "value = pauli.get_transition_amplitude(bra, state)\n", "print(\"transition\", value)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### General linear operators\n", "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`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "expect (-0.12123883067235244+0.004874745096201068j)\n", "transition (-0.19076380005803-0.03521147847936834j)\n" ] } ], "source": [ "from qulacs import GeneralQuantumOperator, PauliOperator, QuantumState\n", "\n", "n = 5\n", "operator = GeneralQuantumOperator(n)\n", "\n", "# Pauli operator can be added\n", "coef = 2.0+0.5j\n", "Pauli_string = \"X 0 X 1 Y 2 Z 4\"\n", "pauli = PauliOperator(Pauli_string,coef)\n", "operator.add_operator(pauli)\n", "# Pauli operator can also be added directly from coefficients and strings\n", "operator.add_operator(0.5j, \"Y 1 Z 4\")\n", "\n", "# Get number of terms\n", "term_count = operator.get_term_count()\n", "\n", "# Get number of quantum bit\n", "qubit_count = operator.get_qubit_count()\n", "\n", "# Get specific terms as PauliOperator\n", "index = 1\n", "pauli = operator.get_term(index)\n", "\n", "\n", "# Expected value calculation \n", "## Generally not self-adjoint, can return complex value\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "value = operator.get_expectation_value(state)\n", "print(\"expect\", value)\n", "\n", "# Transition moment calculation \n", "# The first arguments comes to the bra side\n", "bra = QuantumState(n)\n", "bra.set_Haar_random_state()\n", "value = operator.get_transition_amplitude(bra, state)\n", "print(\"transition\", value)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Store linear operators\n", "`GeneralQuantumOperator` can be converted to/from JSON string." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "original: (1,0) X 2 Y 0 + (0,0.5) Y 1 Z 0\n", "restored: (1,0) X 2 Y 0 + (0,0.5) Y 1 Z 0\n" ] } ], "source": [ "from qulacs import GeneralQuantumOperator\n", "from qulacs import quantum_operator\n", "\n", "o_operator = GeneralQuantumOperator(3)\n", "o_operator.add_operator(1.0, \"X 2 Y 0\")\n", "o_operator.add_operator(0.5j, \"Y 1 Z 0\")\n", "operator_json = o_operator.to_json()\n", "print(\"original:\", o_operator)\n", "\n", "r_operator = quantum_operator.from_json(operator_json)\n", "print(\"restored:\", r_operator)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Generation of observables using OpenFermion\n", "`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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "15\n", "4\n" ] } ], "source": [ "from qulacs.quantum_operator import create_quantum_operator_from_openfermion_file\n", "from qulacs.quantum_operator import create_quantum_operator_from_openfermion_text\n", "\n", "open_fermion_text = \"\"\"\n", "(-0.8126100000000005+0j) [] +\n", "(0.04532175+0j) [X0 Z1 X2] +\n", "(0.04532175+0j) [X0 Z1 X2 Z3] +\n", "(0.04532175+0j) [Y0 Z1 Y2] +\n", "(0.04532175+0j) [Y0 Z1 Y2 Z3] +\n", "(0.17120100000000002+0j) [Z0] +\n", "(0.17120100000000002+0j) [Z0 Z1] +\n", "(0.165868+0j) [Z0 Z1 Z2] +\n", "(0.165868+0j) [Z0 Z1 Z2 Z3] +\n", "(0.12054625+0j) [Z0 Z2] +\n", "(0.12054625+0j) [Z0 Z2 Z3] +\n", "(0.16862325+0j) [Z1] +\n", "(-0.22279649999999998+0j) [Z1 Z2 Z3] +\n", "(0.17434925+0j) [Z1 Z3] +\n", "(-0.22279649999999998+0j) [Z2]\n", "\"\"\"\n", "\n", "operator = create_quantum_operator_from_openfermion_text(open_fermion_text)\n", "print(operator.get_term_count())\n", "print(operator.get_qubit_count())\n", "# In the case of create_quantum_operator_from_openfermion_file, specify the path of the file where the above is written in the argument.\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Hermite operator / observable\n", "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." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "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`.\n", "\n", "#### Separates operators into diagonal and off-diagonal terms\n", "When reading an operator from a file, you can separate it into diagonal and off-diagonal components with the `create_split_observable` function." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "from qulacs.observable import create_split_observable, create_observable_from_openfermion_file\n", "\n", "# H2.txt must be placed in openfermon format beforehand.\n", "operator = create_observable_from_openfermion_file(\"./H2.txt\")\n", "diag, nondiag = create_split_observable(\"./H2.txt\")\n", "print(operator.get_term_count(), diag.get_term_count(), nondiag.get_term_count())\n", "print(operator.get_qubit_count(), diag.get_qubit_count(), nondiag.get_qubit_count())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "#### Compute ground state\n", "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.\n", "\n", "##### Power method" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qulacs import Observable, QuantumState\n", "from qulacs.observable import create_observable_from_openfermion_file\n", "\n", "n = 4\n", "operator = create_observable_from_openfermion_file(\"./H2.txt\")\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "value = operator.solve_ground_state_eigenvalue_by_power_method(state, 50)\n", "print(value)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "##### Arnoldi method" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qulacs import Observable, QuantumState\n", "from qulacs.observable import create_observable_from_openfermion_file\n", "\n", "n = 4\n", "operator = create_observable_from_openfermion_file(\"./H2.txt\")\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "value = operator.solve_ground_state_eigenvalue_by_arnoldi_method(state, 50)\n", "print(value)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "##### Lanczos method" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qulacs import Observable, QuantumState\n", "from qulacs.observable import create_observable_from_openfermion_file\n", "\n", "n = 4\n", "operator = create_observable_from_openfermion_file(\"./H2.txt\")\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "value = operator.solve_ground_state_eigenvalue_by_lanczos_method(state, 50)\n", "print(value)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Apply to a quantum state\n", "An operator can be applied to a quantum state." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qulacs import Observable, QuantumState\n", "from qulacs.observable import create_observable_from_openfermion_file\n", "\n", "n = 4\n", "operator = create_observable_from_openfermion_file(\"./H2.txt\")\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "result = QuantumState(n)\n", "work_state = QuantumState(n)\n", "operator.apply_to_state(work_state, state, result)\n", "print(result)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Quantum Circuits\n", "\n", "### Structure of a quantum circuit\n", "A quantum circuit is represented as a set of quantum gates. For example, a quantum circuit can be configured as follows." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[ 0.35355339+0.j -0.35355339-0.j -0.35355339-0.j 0.35355339+0.j\n", " -0.35355339-0.j 0.35355339+0.j 0.35355339+0.j -0.35355339-0.j]\n" ] } ], "source": [ "from qulacs import QuantumState, QuantumCircuit\n", "from qulacs.gate import Z\n", "n = 3\n", "state = QuantumState(n)\n", "state.set_zero_state()\n", "\n", "circuit = QuantumCircuit(n)\n", "\n", "# Add hadamard gate to quantum circuit\n", "for i in range(n):\n", " circuit.add_H_gate(i)\n", "\n", "# Create gate, which can also be added\n", "for i in range(n):\n", " circuit.add_gate(Z(i))\n", "\n", "# Operate quantum circuit to state\n", "circuit.update_quantum_state(state)\n", "\n", "print(state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Further operations on a quantum circuit\n", "You can add gates at specific positions to a quantum circuit and perform operations such as ```copy``` and ```merge_circuit```. Here is the code that summarizes these operations." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "qubit count = 3\n", "gate count = 3\n", "[ 0.+0.j -1.-0.j 0.+0.j -0.-0.j 0.+0.j -0.-0.j 0.+0.j -0.-0.j]\n" ] } ], "source": [ "from qulacs import QuantumCircuit, QuantumState\n", "from qulacs.gate import H, Z\n", "\n", "n = 3\n", "state = QuantumState(n)\n", "state.set_zero_state()\n", "\n", "circuit = QuantumCircuit(n)\n", "\n", "circuit.add_gate(Z(0))\n", "\n", "# add a gate at the specified position\n", "for i in range(n):\n", " circuit.add_gate(H(i), i)\n", "\n", "circuit.remove_gate(1)\n", "\n", "print(f\"qubit count = {circuit.get_qubit_count()}\")\n", "\n", "print(f\"gate count = {circuit.get_gate_count()}\")\n", "\n", "# get a deep copy of a quantum circuit.\n", "copy_circuit = circuit.copy()\n", "\n", "# merge the gates of the provided quantum circuit as arguments\n", "# modifying the merged side does not affect the side that has been merged\n", "circuit.merge_circuit(copy_circuit)\n", "\n", "circuit.update_quantum_state(state)\n", "print(state.get_vector())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Calculation and optimization of depth of quantum circuits\n", "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.)\n", "\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "10\n", "1\n" ] } ], "source": [ "from qulacs import QuantumCircuit\n", "from qulacs.circuit import QuantumCircuitOptimizer\n", "n = 5\n", "depth = 10\n", "circuit = QuantumCircuit(n)\n", "for d in range(depth):\n", " for i in range(n):\n", " circuit.add_H_gate(i)\n", "\n", "# Calculate the depth (depth=10)\n", "print(circuit.calculate_depth())\n", "\n", "# Optimization\n", "opt = QuantumCircuitOptimizer()\n", "# The maximum quantum gate size allowed to be created\n", "max_block_size = 1\n", "opt.optimize(circuit, max_block_size)\n", "\n", "# Calculate the depth (depth=1へ)\n", "print(circuit.calculate_depth())\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Debugging quantum circuits\n", "When print a quantum circuit, statistical information about the gates included in the quantum circuit will be displayed." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "*** Quantum Circuit Info ***\n", "# of qubit: 5\n", "# of step : 10\n", "# of gate : 50\n", "# of 1 qubit gate: 50\n", "Clifford : yes\n", "Gaussian : no\n", "\n", "\n" ] } ], "source": [ "from qulacs import QuantumCircuit\n", "from qulacs.circuit import QuantumCircuitOptimizer\n", "n = 5\n", "depth = 10\n", "circuit = QuantumCircuit(n)\n", "for d in range(depth):\n", " for i in range(n):\n", " circuit.add_H_gate(i)\n", "\n", "print(circuit)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Store QuantumCircuit\n", "`QuantumCircuit` can be converted to/from JSON string.\n", "If it has unsupported gates, the conversion fails with an error." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "*** Quantum Circuit Info ***\n", "# of qubit: 3\n", "# of step : 2\n", "# of gate : 3\n", "# of 1 qubit gate: 2\n", "# of 2 qubit gate: 1\n", "Clifford : no\n", "Gaussian : no\n", "\n", "\n", "*** Quantum Circuit Info ***\n", "# of qubit: 3\n", "# of step : 2\n", "# of gate : 3\n", "# of 1 qubit gate: 2\n", "# of 2 qubit gate: 1\n", "Clifford : no\n", "Gaussian : no\n", "\n", "\n" ] } ], "source": [ "from qulacs import QuantumCircuit\n", "from qulacs import circuit\n", "\n", "o_circuit = QuantumCircuit(3)\n", "o_circuit.add_H_gate(0)\n", "o_circuit.add_CNOT_gate(0, 1)\n", "o_circuit.add_RZ_gate(2, 0.7)\n", "circuit_json = o_circuit.to_json()\n", "print(o_circuit)\n", "\n", "r_circuit = circuit.from_json(circuit_json)\n", "print(r_circuit)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Quantum circuits can be stored to files in pickle format." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qulacs import QuantumCircuit\n", "import pickle\n", "\n", "circuit = QuantumCircuit(3)\n", "circuit.add_H_gate(0)\n", "circuit.add_CNOT_gate(0, 1)\n", "circuit.add_RZ_gate(2, 0.7)\n", "\n", "# store\n", "with open('circuit.pickle', 'wb') as f:\n", " pickle.dump(circuit, f)\n", "\n", "# load\n", "with open('circuit.pickle', 'rb') as f:\n", " circuit = pickle.load(f)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Parametric Quantum Circuits\n", "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.\n", "\n", "### Application examples of parametric quantum circuits\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " *** Quantum State ***\n", " * Qubit Count : 5\n", " * Dimension : 32\n", " * State vector : \n", " (0.0292587,0.0842756)\n", " (-0.0199201,0.242442)\n", " (0.181468,-0.104986)\n", " (0.0995482,-0.0233467)\n", " (0.16811,0.0345288)\n", " (0.0562338,-0.225101)\n", " (-0.131558,0.100174)\n", " (0.144257,-0.120167)\n", " (-0.173724,-0.0457571)\n", " (-0.142581,-0.0917222)\n", " (0.210296,0.176269)\n", " (0.0014233,0.0511538)\n", " (-0.00440611,0.26444)\n", " (0.0175043,0.0854573)\n", " (-0.197366,0.133705)\n", " (0.191306,0.316103)\n", " (-0.132828,-0.128943)\n", " (-0.00599114,0.03745)\n", " (-0.203638,-0.0249769)\n", " (-0.157577,0.0372862)\n", " (-0.132844,-0.105019)\n", " (-0.136556,-0.0918098)\n", " (-0.0584003,0.043396)\n", " (-0.02902,0.0680596)\n", " (0.0952735,-0.052631)\n", " (0.0738972,-0.127688)\n", " (0.165229,-0.0591462)\n", "(0.0608202,-0.000749349)\n", " (-0.0873545,0.0887971)\n", " (-0.12346,0.0469901)\n", " (0.0344535,-0.00645451)\n", " (-0.216478,0.0550732)\n", "\n", "*** Quantum Circuit Info ***\n", "# of qubit: 5\n", "# of step : 41\n", "# of gate : 171\n", "# of 1 qubit gate: 150\n", "# of 2 qubit gate: 20\n", "# of 3 qubit gate: 0\n", "# of 4 qubit gate: 1\n", "Clifford : no\n", "Gaussian : no\n", "\n", "*** Parameter Info ***\n", "# of parameter: 151\n", "\n" ] } ], "source": [ "from qulacs import ParametricQuantumCircuit\n", "from qulacs import QuantumState\n", "import numpy as np\n", "\n", "n = 5\n", "depth = 10\n", "\n", "# construct parametric quantum circuit with random rotation\n", "circuit = ParametricQuantumCircuit(n)\n", "for d in range(depth):\n", " for i in range(n):\n", " angle = np.random.rand()\n", " circuit.add_parametric_RX_gate(i,angle)\n", " angle = np.random.rand()\n", " circuit.add_parametric_RY_gate(i,angle)\n", " angle = np.random.rand()\n", " circuit.add_parametric_RZ_gate(i,angle)\n", " for i in range(d%2, n-1, 2):\n", " circuit.add_CNOT_gate(i,i+1)\n", "\n", "# add multi-qubit Pauli rotation gate as parametric gate (X_0 Y_3 Y_1 X_4)\n", "target = [0,3,1,4]\n", "pauli_ids = [1,2,2,1]\n", "angle = np.random.rand()\n", "circuit.add_parametric_multi_Pauli_rotation_gate(target, pauli_ids, angle)\n", "\n", "# get variable parameter count, and get current parameter\n", "parameter_count = circuit.get_parameter_count()\n", "param = [circuit.get_parameter(ind) for ind in range(parameter_count)]\n", "\n", "# set 3rd parameter to 0\n", "circuit.set_parameter(3, 0.)\n", "\n", "# update quantum state\n", "state = QuantumState(n)\n", "circuit.update_quantum_state(state)\n", "\n", "# output state and circuit info\n", "print(state)\n", "print(circuit)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Compute a gradient of parametric quantum circuit\n", "You can compute a gradient of parametric circuit by `GradCalculator` or `ParametricQuantumCircuit.backprop()`.\n", "\n", "- In `GradCalculator`, compute a gradient by calculating expected value with `CausalConeSimulator`.\n", "- In `ParametricQuantumCircuit.backprop()`, compute a gradient by back propagation." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[(0.1329240611221506+0j), (0.06968868323709176+0j), (0.14726262077628172+0j)]\n", "[(0.1329240611221506+0j), (0.06968868323709176+0j), (0.14726262077628172+0j)]\n", "[0.1329240611221506, 0.06968868323709171, 0.14726262077628177]\n" ] } ], "source": [ "from qulacs import ParametricQuantumCircuit, GradCalculator, Observable\n", "\n", "n = 2\n", "observable = Observable(n)\n", "observable.add_operator(1.0, \"X 0\")\n", "circuit = ParametricQuantumCircuit(n)\n", "\n", "theta = [2.2, 1.4, 0.8]\n", "circuit.add_parametric_RX_gate(0, theta[0])\n", "circuit.add_parametric_RY_gate(0, theta[1])\n", "circuit.add_parametric_RZ_gate(0, theta[2])\n", "\n", "# GradCalculatorの場合\n", "gcalc = GradCalculator()\n", "print(gcalc.calculate_grad(circuit, observable))\n", "# 第三引数に回転角を指定することも可能\n", "print(gcalc.calculate_grad(circuit, observable, theta))\n", "# Backpropを使って求めた場合\n", "print(circuit.backprop(observable))\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Store parametric quantum circuits\n", "\n", "Parametric quantum circuits can be converted to/from JSON string.\n", "If it has unsupported gates, the conversion fails with an error." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "*** Quantum Circuit Info ***\n", "# of qubit: 3\n", "# of step : 2\n", "# of gate : 3\n", "# of 1 qubit gate: 2\n", "# of 2 qubit gate: 0\n", "# of 3 qubit gate: 1\n", "Clifford : no\n", "Gaussian : no\n", "\n", "*** Parameter Info ***\n", "# of parameter: 1\n", "\n", "*** Quantum Circuit Info ***\n", "# of qubit: 3\n", "# of step : 2\n", "# of gate : 3\n", "# of 1 qubit gate: 2\n", "# of 2 qubit gate: 0\n", "# of 3 qubit gate: 1\n", "Clifford : no\n", "Gaussian : no\n", "\n", "*** Parameter Info ***\n", "# of parameter: 1\n", "\n" ] } ], "source": [ "from qulacs import ParametricQuantumCircuit\n", "from qulacs import circuit\n", "\n", "o_circuit = ParametricQuantumCircuit(3)\n", "o_circuit.add_H_gate(0)\n", "o_circuit.add_parametric_RX_gate(1, 0.3)\n", "o_circuit.add_multi_Pauli_rotation_gate([0, 1, 2], [1, 3, 2], 1.4)\n", "circuit_json = o_circuit.to_json()\n", "print(o_circuit)\n", "\n", "r_circuit = circuit.from_json(circuit_json)\n", "print(r_circuit)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Parametric quantum circuits can be converted to files in pickle format." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from qulacs import ParametricQuantumCircuit\n", "from qulacs import circuit\n", "\n", "circuit = ParametricQuantumCircuit(3)\n", "circuit.add_H_gate(0)\n", "circuit.add_parametric_RX_gate(1, 0.3)\n", "circuit.add_multi_Pauli_rotation_gate([0, 1, 2], [1, 3, 2], 1.4)\n", "\n", "# store\n", "with open('circuit.pickle', 'wb') as f:\n", " pickle.dump(circuit, f)\n", "\n", "# load\n", "with open('circuit.pickle', 'rb') as f:\n", " circuit = pickle.load(f)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Simulator\n", "### `QuantumCircuitSimulator`\n", "You can manage a circuit and quantum states together. It has a buffer for quantum state to swap the state to use." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "gate_count: 3\n", " *** Quantum State ***\n", " * Qubit Count : 3\n", " * Dimension : 8\n", " * State vector : \n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "\n", "expectation_value: 0j\n", "swap\n", " *** Quantum State ***\n", " * Qubit Count : 3\n", " * Dimension : 8\n", " * State vector : \n", " (-0.298916,0.160953)\n", " (0.015405,-0.237144)\n", " (-0.215765,0.171064)\n", "(-0.257959,-0.0506326)\n", " (-0.121612,0.0424348)\n", "(-0.0329899,-0.400262)\n", " (0.327376,-0.414262)\n", " (0.345253,0.327824)\n", "\n", " *** Quantum State ***\n", " * Qubit Count : 3\n", " * Dimension : 8\n", " * State vector : \n", "(1,0)\n", "(0,0)\n", "(0,0)\n", "(0,0)\n", "(0,0)\n", "(0,0)\n", "(0,0)\n", "(0,0)\n", "\n", " *** Quantum State ***\n", " * Qubit Count : 3\n", " * Dimension : 8\n", " * State vector : \n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "(0.353553,0)\n", "\n" ] } ], "source": [ "from qulacs import QuantumState, QuantumCircuit, QuantumCircuitSimulator, Observable\n", "n = 3\n", "state = QuantumState(n)\n", "\n", "# 回路を作成\n", "circuit = QuantumCircuit(n)\n", "for i in range(n):\n", " circuit.add_H_gate(i)\n", "\n", "# シミュレータクラスを作成\n", "sim = QuantumCircuitSimulator(circuit, state)\n", "\n", "# 基底を二進数と見た時の整数値を入れて、その状態に初期化\n", "sim.initialize_state(0)\n", "\n", "# ゲート数\n", "print(\"gate_count: \", sim.get_gate_count())\n", "\n", "# 実行\n", "sim.simulate()\n", "\n", "# 量子状態を表示\n", "print(state)\n", "\n", "# 期待値\n", "observable = Observable(1)\n", "observable.add_operator(1.0, \"Z 0\")\n", "print(\"expectation_value: \", sim.get_expectation_value(observable))\n", "\n", "# 量子状態を入れ替え\n", "print(\"swap\")\n", "sim.swap_state_and_buffer()\n", "# ランダムな純粋状態へ初期化\n", "sim.initialize_random_state(seed=0)\n", "sim.simulate()\n", "print(state)\n", "\n", "# 量子状態をコピー(バッファ->現状態)\n", "sim.copy_state_from_buffer()\n", "sim.simulate()\n", "print(state)\n", "\n", "# 量子状態をコピー(現状態->バッファ)\n", "sim.copy_state_to_buffer()\n", "sim.simulate()\n", "print(state)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### `NoiseSimulator`\n", "The `NoiseSimulator` allows you to run your circuit in a simulated noise environment.\n", "\n", "To set up noise, you should add a gate to the circuit using `add_noise_gate()`.\n", "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.\n", "In the case of a two-qubit gate, you can use `\"Depolarizing\"` only." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ " *** Quantum State ***\n", " * Qubit Count : 3\n", " * Dimension : 8\n", " * State vector : \n", " (0.424423,-0.125395)\n", " (0.0193726,-0.298116)\n", " (-0.357495,0.227471)\n", " (0.0119428,0.13876)\n", " (-0.351555,0.0521885)\n", " (0.230969,0.21148)\n", " (0.274671,-0.0305064)\n", "(-0.462659,-0.0337342)\n", "\n" ] } ], "source": [ "import random\n", "from qulacs import QuantumState, QuantumCircuit, NoiseSimulator\n", "from qulacs.gate import sqrtX, sqrtY, T, CNOT, CZ\n", "\n", "n = 3\n", "depth = 10\n", "one_qubit_noise = [\"Depolarizing\", \"BitFlip\", \"Dephasing\", \"IndependentXZ\", \"AmplitudeDamping\"]\n", "circuit = QuantumCircuit(n)\n", "\n", "for d in range(depth):\n", " for i in range(n):\n", " r = random.randint(0, 4)\n", " noise_type = random.randint(0, 4)\n", " if r == 0:\n", " circuit.add_noise_gate(sqrtX(i), one_qubit_noise[noise_type], 0.01)\n", " elif r == 1:\n", " circuit.add_noise_gate(sqrtY(i), one_qubit_noise[noise_type], 0.01)\n", " elif r == 2:\n", " circuit.add_noise_gate(T(i), one_qubit_noise[noise_type], 0.01)\n", " elif r == 3:\n", " if i + 1 < n:\n", " circuit.add_noise_gate(CNOT(i, i+1), \"Depolarizing\", 0.01)\n", " elif r == 4:\n", " if i + 1 < n:\n", " circuit.add_noise_gate(CZ(i, i+1), \"Depolarizing\", 0.01)\n", "\n", "state = QuantumState(n)\n", "state.set_Haar_random_state()\n", "sim = NoiseSimulator(circuit, state)\n", "sim.execute(100)\n", "print(state)\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### `CausalConeSimulator`\n", "`CausalConeSimulator` allows you to extract the gates associated with a given observable by traversing the circuit in reverse.\n", "Only the extracted gates can be applied to obtain the expected value of the physical quantity.\n", "\n", "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." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(0.2919265817264289+0j)\n" ] } ], "source": [ "from qulacs import QuantumState, ParametricQuantumCircuit, CausalConeSimulator, Observable\n", "n = 100\n", "observable = Observable(1)\n", "observable.add_operator(1.0, \"Z 0\")\n", "circuit = ParametricQuantumCircuit(n)\n", "for i in range(n):\n", " circuit.add_parametric_RX_gate(i, 1.0)\n", " circuit.add_parametric_RY_gate(i, 1.0)\n", "\n", "ccs = CausalConeSimulator(circuit, observable)\n", "print(ccs.get_expectation_value())\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.9.2 64-bit", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" }, "vscode": { "interpreter": { "hash": "949777d72b0d2535278d3dc13498b2535136f6dfe0678499012e853ee9abcab1" } } }, "nbformat": 4, "nbformat_minor": 4 }