Comments (21)
@imppresser see the example here:
https://faculty.washington.edu/seattle/physics541/11solved.pdf
from quantum.
One naive example for the expectance calculation could be
from paddle_quantum import Hamiltonian
from paddle_quantum.state import random_state
psi = random_state(2)
pauli_str = [(1.0, 'Z0, Z1'), (2.0, 'X0, Y1')]
H = Hamiltonian(pauli_str)
print("The expectation value of the observable ZZ + 2XY is", psi.expec_val(H))
Above example cannot be used in a QNN, in which case you should try
from paddle_quantum.loss import ExpecVal
loss_fcn = ExpecVal(H)
print("The loss value is", loss_fcn(psi))
from quantum.
Thank you very much.
For teaching purposes, is this the preferred method?
%reset -f
import numpy as np
from numpy import pi as PI
import paddle
import paddle_quantum
from paddle import matmul
from paddle_quantum.ansatz import Circuit
from paddle_quantum.qinfo import random_pauli_str_generator, pauli_str_to_matrix
from paddle_quantum.linalg import dagger
from paddle_quantum import Hamiltonian
from paddle_quantum.state import random_state
x0=np.array([1/np.sqrt(2), 1/np.sqrt(2)])
x1=np.array([1,0])
x2=np.array([0,1])
state_lst=(x0,x1,x2)
pauli_str_lst = ([(1.0, 'X0')],[(1.0, 'Y0')],[(1.0, 'Z0')])
for gate in pauli_str_lst:
# print (gate)
H = Hamiltonian(gate)
for state in state_lst:
psi=paddle_quantum.State(paddle.to_tensor(state,dtype='complex64'), dtype='complex64')
print("Gate {}, State {}, Exp-val {}".format(gate, psi, psi.expec_val(H).numpy()))
Gate [(1.0, 'X0')], State [0.70710677+0.j 0.70710677+0.j], Exp-val [0.99999994]
Gate [(1.0, 'X0')], State [1.+0.j 0.+0.j], Exp-val [0.]
Gate [(1.0, 'X0')], State [0.+0.j 1.+0.j], Exp-val [0.]
Gate [(1.0, 'Y0')], State [0.70710677+0.j 0.70710677+0.j], Exp-val [0.]
Gate [(1.0, 'Y0')], State [1.+0.j 0.+0.j], Exp-val [0.]
Gate [(1.0, 'Y0')], State [0.+0.j 1.+0.j], Exp-val [0.]
Gate [(1.0, 'Z0')], State [0.70710677+0.j 0.70710677+0.j], Exp-val [0.]
Gate [(1.0, 'Z0')], State [1.+0.j 0.+0.j], Exp-val [1.]
Gate [(1.0, 'Z0')], State [0.+0.j 1.+0.j], Exp-val [-1.]
Thanks
from quantum.
Some codes in terms of Hamiltonian
and State
could be further simplified, as shown below
import numpy as np
import paddle_quantum as pq
from paddle_quantum import Hamiltonian
from paddle_quantum.state import State
pq.set_backend('state_vector')
pq.set_dtype('complex128')
x0 = np.array([1, 1]) / np.sqrt(2)
x1 = np.array([1, 0])
x2 = np.array([0, 1])
state_list = (x0,x1,x2)
pauli_str_list = ([(1.0, 'X0')],[(1.0, 'Y0')],[(1.0, 'Z0')])
for pauli_str in pauli_str_list:
H = Hamiltonian(pauli_str)
for vec in state_list:
psi = State(vec)
print(f"Observable {H.pauli_words}, State {psi.numpy()}, Exp val {psi.expec_val(H)}")
You can refer to the API documents of Hamiltonian
and State
for more information.
from quantum.
Here,
from sympy import Matrix, symbols, sqrt, init_printing
from sympy.physics.quantum import TensorProduct
from IPython.display import display_pretty
init_printing(use_latex=True)
U_I = Matrix([[1,0],
[0,1]])
U_H = 1/sqrt(2)*Matrix([[1, 1],
[1,-1]])
U_Z=Matrix(2,2,[1,0,0,-1])
# U_Z=Matrix(2,2,[1,0,0,-1])
U_ZZ = TensorProduct(U_Z,U_Z)
phi_plus = Matrix(1,4,np.array([1, 0, 0, 1])/np.sqrt(2)).T
# phi_plus*(U_ZZ*phi_plus)
U_ZZ, phi_plus, U_ZZ*phi_plus, U_Z, U_ZZ, phi_plus.T*(U_ZZ*phi_plus)
I get expectation value of 1 from phi_plus.T*(U_ZZ*phi_plus)
.
But in paddle:
# matmul(matmul(U, self.rho), dagger(U))
# paddle.kron(proj, X)
U_Z=paddle.to_tensor([[1,0],[0,-1]], dtype='complex128')
phi_plus = paddle.Tensor(np.array([1, 0, 0, 1])/np.sqrt(2))# | Phi^+ >
phi_plus=paddle.unsqueeze(phi_plus, axis=1)
# U_ZZ = paddle.kron(U_Z,pq.linalg.dagger(U_Z)).numpy()
U_ZZ = paddle.kron(U_Z,U_Z)
exp_val=(phi_plus.T*(U_ZZ*phi_plus)).numpy()
U_ZZ, phi_plus, U_ZZ*phi_plus, exp_val
I get a matrix instead of a scaler, what am I doing wrong?
In numpy:
U_Z=[[1,0],[0,-1]]
phi_plus = (np.matrix([1, 0, 0, 1])/np.sqrt(2)).T# | Phi^+ >
phi_plus.conj().T*(np.kron(U_Z, U_Z)*phi_plus)
matrix([[1.]])
from quantum.
?
from quantum.
The operation *
for matrix-like classes (such as sympy.Matrix
, numpy.matrix
) means matrix multiplication, whereas the operation *
for array-like classes (such as numpy.ndarray
, paddle.Tensor
) means entry-wise multiplication. Please use the symbol @
or the function paddle.matmul
instead.
from quantum.
One naive example for the expectance calculation could be
from paddle_quantum import Hamiltonian from paddle_quantum.state import random_state psi = random_state(2) pauli_str = [(1.0, 'Z0, Z1'), (2.0, 'X0, Y1')] H = Hamiltonian(pauli_str) print("The expectation value of the observable ZZ + 2XY is", psi.expec_val(H))Above example cannot be used in a QNN, in which case you should try
from paddle_quantum.loss import ExpecVal loss_fcn = ExpecVal(H) print("The loss value is", loss_fcn(psi))
Hey, thank you, but what if I need to compute <ψ|H^2|ψ>, how to use the psi.expec_val(H)?
from quantum.
Hi there. The function State.expec_val()
only accepts inputs from class Hamiltonian
, to be compatible with the situation when the backend is switched from simulators to real quantum devices.
To calculate
from paddle_quantum import Hamiltonian
from paddle_quantum.state import random_state
from paddle_quantum.qinfo import random_pauli_str_generator
num_qubits = 3
psi = random_state(num_qubits)
H = Hamiltonian(random_pauli_str_generator(num_qubits))
H_matrix = paddle.to_tensor(H.construct_h_matrix())
expect_value = psi.bra @ H_matrix @ H_matrix @ psi.ket
print("The pauli string of this Hamiltonian is \n", H.pauli_str)
print("The expectation value is", expect_value.item())
The pauli string of this Hamiltonian is
[[0.6976072696164013, 'Z1,Z0'], [0.6145107870116349, 'Z1,X0'], [-0.5089016842519825, 'Y1,Y2,Y0']]
The expectation value is (1.177162766456604-2.9802322387695312e-08j)
from quantum.
@imppresser see the example here: https://faculty.washington.edu/seattle/physics541/11solved.pdf
Thank you for your detailed lecture note, caculating the H^2 is surely the way. However, in my case need more general way of implementing code of H^2, because the variety of H. Very happy to find the course, it will help a lot!
from quantum.
Hi there. The function
State.expec_val()
only accepts inputs from classHamiltonian
, to be compatible with the situation when the backend is switched from simulators to real quantum devices.To calculate ⟨ψ|H2|ψ⟩, you can use the bra-ket notation and matrix multiplications to complete the job.
from paddle_quantum import Hamiltonian from paddle_quantum.state import random_state from paddle_quantum.qinfo import random_pauli_str_generator num_qubits = 3 psi = random_state(num_qubits) H = Hamiltonian(random_pauli_str_generator(num_qubits)) H_matrix = paddle.to_tensor(H.construct_h_matrix()) expect_value = psi.bra @ H_matrix @ H_matrix @ psi.ket print("The pauli string of this Hamiltonian is \n", H.pauli_str) print("The expectation value is", expect_value.item())The pauli string of this Hamiltonian is [[0.6976072696164013, 'Z1,Z0'], [0.6145107870116349, 'Z1,X0'], [-0.5089016842519825, 'Y1,Y2,Y0']] The expectation value is (1.177162766456604-2.9802322387695312e-08j)
Thanks for the detailed feedback. I noticed the "expect_val()" function changed (for compatibility). The solution you give will help me out!
from quantum.
When N(as qubits) turns big like 18, or above, it shows errors for it cannot allocate this big memory. But using "ExpecVal(H)" would not cause error even as large as 20+. If it is possible to run big tasks while expect_value(H^2)?
from quantum.
Are you using a GPU? Can I see the a full code snippet?
from quantum.
Are you using a GPU? Can I see the a full code snippet?
Not using GPU. The problem is to construct h_matrix, it is natural cannot build 2^18 x 2^18 complex64 matrix on PC, it will need 500+GB.
from quantum.
You have reached another motivation to use the class Hamiltonian
. To be specific, the matrices of physical Hamiltonians are usually enriched with zero entries, i.e. the sparse matrix. The linear operations for such matrices can be sped up by tensor contractions (see paddle.einsum
used in Paddle Quantum), saving a significant amout of computational resources.
Regarding your question, multiplication for the Hamiltonian
class is not yet implemented. But, it has been included for future discussions. For now one naive and possibly expensive approach is to extract the Pauli strings of
and then feed the result back into ExpecVal
or State.expec_val
.
from quantum.
You have reached another motivation to use the class
Hamiltonian
. To be specific, the matrices of physical Hamiltonians are usually enriched with zero entries, i.e. the sparse matrix. The linear operations for such matrices can be sped up by tensor contractions (seepaddle.einsum
used in Paddle Quantum), saving a significant amout of computational resources.Regarding your question, multiplication for the
Hamiltonian
class is not yet implemented. But, it has been included for future discussions. For now one naive and possibly expensive approach is to extract the Pauli strings of H, calculate the Pauli strings of H2 using the identity of Pauli basis σj σk=δjk I+iϵjkl σl, and then feed the result back intoExpecVal
orState.expec_val
.
I will try this, thank you. Here I have two questions.
- I use HVA Ansatz(VQE) to get the ground state energy in 1d Transverse-field Ising model, and can get energy below the real ground state energy, when N=4 with periodic boundry condition and certain transverse strength g=1, the ground state energy is -5.22625186 (Exact Diagonalization). The Loss gives me -5.226253032684326 which belows the real ground state energy. If that is possible, why?
- I use "state.bra @ H_matrix @ state.ket" to caculate the
$\langle \psi | H |\psi\rangle$ , the result is slightly different from the "ExpecVal or State.expec_val". How could that be?
regE: -5.226253509521484 loss: -5.226253032684326 loss_expec_val: -5.226253032684326
regE is the result ofstate.bra @ H_matrix @ state.ket
; loss is the result ofExpecVal(Hamiltonian)
; loss_expec_val is the result ofState.expec_val(Hamiltonian)
Many thanks to your support!
from quantum.
You have reached another motivation to use the class
Hamiltonian
. To be specific, the matrices of physical Hamiltonians are usually enriched with zero entries, i.e. the sparse matrix. The linear operations for such matrices can be sped up by tensor contractions (seepaddle.einsum
used in Paddle Quantum), saving a significant amout of computational resources.Regarding your question, multiplication for the
Hamiltonian
class is not yet implemented. But, it has been included for future discussions. For now one naive and possibly expensive approach is to extract the Pauli strings of H, calculate the Pauli strings of H2 using the identity of Pauli basis σj σk=δjk I+iϵjkl σl, and then feed the result back intoExpecVal
orState.expec_val
.
I tried to construct pauli string using σj σk=δjk I+iϵjkl σl
, one simple example like Z0X0=iY0
, the coefficient will need to multiply i
. An original pauli string [[1.0,'Z0, X0']] (cannot use directly, will cause error AssertionError: each Pauli operator should act on different qubit
), converted to [[1.0j,'Y0']], It will cause error, because it only accept coefficient as float
type.
from quantum.
- I use HVA Ansatz(VQE) to get the ground state energy in 1d Transverse-field Ising model, and can get energy below the real ground state energy, when N=4 with periodic boundry condition and certain transverse strength g=1, the ground state energy is -5.22625186 (Exact Diagonalization). The Loss gives me -5.226253032684326 which belows the real ground state energy. If that is possible, why?
- I use "state.bra @ H_matrix @ state.ket" to caculate the ⟨ψ|H|ψ⟩, the result is slightly different from the "ExpecVal or State.expec_val". How could that be?
The variations among State.expec_val
, state.bra @ H_matrix @ state.ket
and the theorectical value are due to the inevitable precision problem, which increases exponentially as the number of qubits gets larger (and hence motivates the development of quantum computers). Particularly, the precision differences between State.expec_val
and state.bra @ H_matrix @ state.ket
are essentially the difference between tensor contractions and matrix multiplications, where tensor contraction is slightly better since it deals with smaller matrices.
To relieve the precision problem when the qubit size is not too large, you can switch the data type (dtype) from complex64
to complex128
, improving the precision from
import paddle_quantum as pq
from paddle_quantum import Hamiltonian
from paddle_quantum.state import ghz_state
from paddle_quantum.qinfo import random_pauli_str_generator
num_qubits = 4
pauli_str = random_pauli_str_generator(num_qubits, terms=10)
# Compute error from imaginary part of expectation value
def expect_error() -> float:
psi = ghz_state(num_qubits)
H = Hamiltonian(pauli_str)
H_matrix = paddle.to_tensor(H.construct_h_matrix())
value = psi.bra @ H_matrix @ H_matrix @ psi.ket
return abs(value.imag().item())
# Calculate the expectance value under complex64
pq.set_dtype('complex64')
error_64 = expect_error()
# Calculate the expectance value under complex128
pq.set_dtype('complex128')
error_128 = expect_error()
print("The error for complex64 is", error_64)
print("The error for complex128 is", error_128)
The error for complex64 is 1.1195256277574117e-08
The error for complex128 is 9.813077866773593e-18
Note that the function paddle_quantum.set_dype
should be excecuted at the very beginning of the program, so that every operation in Paddle Quantum can be computed under dtype complex128
. Also, as a trade-off, computations in complex128
are slower than those in complex64
.
from quantum.
I tried to construct pauli string using
σj σk=δjk I+iϵjkl σl
, one simple example likeZ0X0=iY0
, the coefficient will need to multiplyi
. An original pauli string [[1.0,'Z0, X0']] (cannot use directly, will cause errorAssertionError: each Pauli operator should act on different qubit
), converted to [[1.0j,'Y0']], It will cause error, because it only accept coefficient asfloat
type.
The reason why the class Hamiltonian
only accepts real coefficients, is that Hamiltonians are Hermitian matrices and thus have only real eigenvalues. For example ZX
cannot be a Hamiltonian since its eigenvalues are i
and -i
.
For the same reason, I believe every imaginary coefficient occured in one term of
Such logic may need to be considered during the construction of Pauli strings of
from quantum.
I tried to construct pauli string using
σj σk=δjk I+iϵjkl σl
, one simple example likeZ0X0=iY0
, the coefficient will need to multiplyi
. An original pauli string [[1.0,'Z0, X0']] (cannot use directly, will cause errorAssertionError: each Pauli operator should act on different qubit
), converted to [[1.0j,'Y0']], It will cause error, because it only accept coefficient asfloat
type.The reason why the class
Hamiltonian
only accepts real coefficients, is that Hamiltonians are Hermitian matrices and thus have only real eigenvalues. For exampleZX
cannot be a Hamiltonian since its eigenvalues arei
and-i
.For the same reason, I believe every imaginary coefficient occured in one term of H2 can be vanished somewhere for meeting its complex conjugates. For example, consider H=X+Z. Then
H2=X2+XZ+ZX+Z2=I−iY+iY+I=2I.
Such logic may need to be considered during the construction of Pauli strings of H2.
Yes, indeed. I retain every term when I trying to build the H^2 pauli string function. And I should care the imaginary coefficient can be vanished, thanks!
from quantum.
- I use HVA Ansatz(VQE) to get the ground state energy in 1d Transverse-field Ising model, and can get energy below the real ground state energy, when N=4 with periodic boundry condition and certain transverse strength g=1, the ground state energy is -5.22625186 (Exact Diagonalization). The Loss gives me -5.226253032684326 which belows the real ground state energy. If that is possible, why?
- I use "state.bra @ H_matrix @ state.ket" to caculate the ⟨ψ|H|ψ⟩, the result is slightly different from the "ExpecVal or State.expec_val". How could that be?
The variations among
State.expec_val
,state.bra @ H_matrix @ state.ket
and the theorectical value are due to the inevitable precision problem, which increases exponentially as the number of qubits gets larger (and hence motivates the development of quantum computers). Particularly, the precision differences betweenState.expec_val
andstate.bra @ H_matrix @ state.ket
are essentially the difference between tensor contractions and matrix multiplications, where tensor contraction is slightly better since it deals with smaller matrices.To relieve the precision problem when the qubit size is not too large, you can switch the data type (dtype) from
complex64
tocomplex128
, improving the precision from O( 10−8 ) to O( 10−16 ) in average, as demonstrated in the following example:import paddle_quantum as pq from paddle_quantum import Hamiltonian from paddle_quantum.state import ghz_state from paddle_quantum.qinfo import random_pauli_str_generator num_qubits = 4 pauli_str = random_pauli_str_generator(num_qubits, terms=10) # Compute error from imaginary part of expectation value def expect_error() -> float: psi = ghz_state(num_qubits) H = Hamiltonian(pauli_str) H_matrix = paddle.to_tensor(H.construct_h_matrix()) value = psi.bra @ H_matrix @ H_matrix @ psi.ket return abs(value.imag().item()) # Calculate the expectance value under complex64 pq.set_dtype('complex64') error_64 = expect_error() # Calculate the expectance value under complex128 pq.set_dtype('complex128') error_128 = expect_error() print("The error for complex64 is", error_64) print("The error for complex128 is", error_128)The error for complex64 is 1.1195256277574117e-08 The error for complex128 is 9.813077866773593e-18
Note that the function
paddle_quantum.set_dype
should be excecuted at the very beginning of the program, so that every operation in Paddle Quantum can be computed under dtypecomplex128
. Also, as a trade-off, computations incomplex128
are slower than those incomplex64
.
Nice solution, I will try, thanks 👍
from quantum.
Related Issues (20)
- 【PaddlePaddle Hackathon】80 多量子比特独立系统的 Bloch 球展示
- 【PaddlePaddle Hackathon】81 时间演化电路的性能优化 HOT 2
- 【PaddlePaddle Hackathon】82 基于量子卷积神经网络的图片分类
- 【PaddlePaddle Hackathon】Paddle Quantum 任务合集
- 量桨2.1.3版本导入化学分子库报错 HOT 4
- 相关数学推导咨询 HOT 1
- ImportError: cannot import name 'State' from 'sre_parse' HOT 6
- There are no kernels which are registered in the einsum operator. [Hint: Expected kernels_iter != all_op_kernels.end(), but received kernels_iter == all_op_kernels.end().] HOT 3
- (NotFound) There are no kernels which are registered in the einsum operator. HOT 12
- 现在使用量子计算来训练模型,会有速度上的优势吗? HOT 2
- Integration on OSX with the M1 chip (arm64)? HOT 9
- Many of the examples dont work HOT 6
- Input object type error or incompatible array data type. tensor.set() supports array with bool, float16, float32, float64, int8, int16, int32, int64, uint8 or uint16, please check your input or input array data type. (at /paddle/paddle/fluid/pybind/tensor_py.h:411) HOT 6
- Importing `paddle_quantum` generates warnings that can't be silenced HOT 4
- Medical image classification HOT 1
- Is it possible to use ProcessPoolExecutor to accelerate the for loop in the forward method in QApproximating_EN.ipynb HOT 1
- In the code of VQSVD, why the matrix M doesn`t pre-decomposition to several unitary as the source manuscript?
- 量桨为何不在百度飞桨上更新了?有其他可以在线使用量桨的云平台吗?
- 量子表达能力的例子报错
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from quantum.