Quantum Machine Learning Module¶
Quantum Computing Layer¶
QuantumLayer¶
QuantumLayer is a package class of autograd module that supports ariational quantum circuits. You can define a function as an argument, such as qprog_with_measure
, This function needs to contain the quantum circuit defined by pyQPanda: It generally contains coding-circuit, evolution-circuit and measurement-operation.
This QuantumLayer class can be embedded into the hybrid quantum classical machine learning model and minimize the objective function or loss function of the hybrid quantum classical model through the classical gradient descent method.
You can specify the gradient calculation method of quantum circuit parameters in QuantumLayer
by change the parameter diff_method
. QuantumLayer
currently supports two methods, one is finite_diff
and the other is parameter-shift
methods.
The finite_diff
method is one of the most traditional and common numerical methods for estimating function gradient.The main idea is to replace partial derivatives with differences:
For the parameter-shift
method we use the objective function, such as:
It is theoretically possible to calculate the gradient of parameters about Hamiltonian in a quantum circuit by the more precise method: parameter-shift
.
- class pyvqnet.qnn.quantumlayer.QuantumLayer(qprog_with_measure, para_num, machine_type_or_cloud_token, num_of_qubits: int, num_of_cbits: int = 1, diff_method: str = 'parameter_shift', delta: float = 0.01, dtype=None, name='')¶
Abstract calculation module for variational quantum circuits. It simulates a parameterized quantum circuit and gets the measurement result. QuantumLayer inherits from Module ,so that it can calculate gradients of circuits parameters,and train variational quantum circuits model or embed variational quantum circuits into hybird quantum and classic model.
This class dos not need you to initialize virtual machine in the
qprog_with_measure
function.- Parameters:
qprog_with_measure – callable quantum circuits functions ,cosntructed by qpanda
para_num – int - Number of parameter
machine_type_or_cloud_token – qpanda machine type or pyQPANDA QCLOUD token : https://pyqpanda-toturial.readthedocs.io/zh/latest/Realchip.html
num_of_qubits – num of qubits
num_of_cbits – num of classic bits
diff_method – ‘parameter_shift’ or ‘finite_diff’
delta – delta for diff
dtype – The data type of the parameter, defaults: None, use the default data type kfloat32, which represents a 32-bit floating point number.
name – name of the output layer
- Returns:
a module can calculate quantum circuits .
Note
qprog_with_measure is quantum circuits function defined in pyQPanda :https://pyqpanda-toturial.readthedocs.io/zh/latest/QCircuit.html.
This function should contain following parameters,otherwise it can not run properly in QuantumLayer.
qprog_with_measure (input,param,qubits,cbits,m_machine)
input: array_like input 1-dim classic data
param: array_like input 1-dim quantum circuit’s parameters
qubits: qubits allocated by QuantumLayer
cbits: cbits allocated by QuantumLayer.if your circuits does not use cbits,you should also reserve this parameter.
m_machine: simulator created by QuantumLayer
Use the
m_para
attribute of QuantumLayer to get the training parameters of the variable quantum circuit. The parameter is aQTensor
class, which can be converted into a numpy array using theto_numpy()
interface.Example:
import pyqpanda as pq from pyvqnet.qnn.measure import ProbsMeasure from pyvqnet.qnn.quantumlayer import QuantumLayer import numpy as np from pyvqnet.tensor import QTensor def pqctest (input,param,qubits,cbits,m_machine): circuit = pq.QCircuit() circuit.insert(pq.H(qubits[0])) circuit.insert(pq.H(qubits[1])) circuit.insert(pq.H(qubits[2])) circuit.insert(pq.H(qubits[3])) circuit.insert(pq.RZ(qubits[0],input[0])) circuit.insert(pq.RZ(qubits[1],input[1])) circuit.insert(pq.RZ(qubits[2],input[2])) circuit.insert(pq.RZ(qubits[3],input[3])) circuit.insert(pq.CNOT(qubits[0],qubits[1])) circuit.insert(pq.RZ(qubits[1],param[0])) circuit.insert(pq.CNOT(qubits[0],qubits[1])) circuit.insert(pq.CNOT(qubits[1],qubits[2])) circuit.insert(pq.RZ(qubits[2],param[1])) circuit.insert(pq.CNOT(qubits[1],qubits[2])) circuit.insert(pq.CNOT(qubits[2],qubits[3])) circuit.insert(pq.RZ(qubits[3],param[2])) circuit.insert(pq.CNOT(qubits[2],qubits[3])) #print(circuit) prog = pq.QProg() prog.insert(circuit) # pauli_dict = {'Z0 X1':10,'Y2':-0.543} rlt_prob = ProbsMeasure([0,2],prog,m_machine,qubits) return rlt_prob pqc = QuantumLayer(pqctest,3,"cpu",4,1) #classic data as input input = QTensor([[1,2,3,4],[40,22,2,3],[33,3,25,2.0]] ) #forward circuits rlt = pqc(input) grad = QTensor(np.ones(rlt.data.shape)*1000) #backward circuits rlt.backward(grad) print(rlt) # [ # [0.2500000, 0.2500000, 0.2500000, 0.2500000], # [0.2500000, 0.2500000, 0.2500000, 0.2500000], # [0.2500000, 0.2500000, 0.2500000, 0.2500000] # ]
QuantumLayerV2¶
If you are more familiar with pyQPanda syntax, please using QuantumLayerV2 class, you can define the quantum circuits function by using qubits
, cbits
and machine
, then take it as a argument qprog_with_measure
of QuantumLayerV2.
- class pyvqnet.qnn.quantumlayer.QuantumLayerV2(qprog_with_measure, para_num, diff_method: str = 'parameter_shift', delta: float = 0.01, dtype=None, name='')¶
Abstract calculation module for variational quantum circuits. It simulates a parameterized quantum circuit and gets the measurement result. QuantumLayer inherits from Module ,so that it can calculate gradients of circuits parameters,and train variational quantum circuits model or embed variational quantum circuits into hybird quantum and classic model.
To use this module, you need to create your quantum virtual machine and allocate qubits and cbits.
- Parameters:
qprog_with_measure – callable quantum circuits functions ,cosntructed by qpanda
para_num – int - Number of parameter
diff_method – ‘parameter_shift’ or ‘finite_diff’
delta – delta for diff
dtype – The data type of the parameter, defaults: None, use the default data type kfloat32, which represents a 32-bit floating point number.
name – name of the output layer
- Returns:
a module can calculate quantum circuits .
Note
qprog_with_measure is quantum circuits function defined in pyQPanda :https://pyqpanda-toturial.readthedocs.io/zh/latest/QCircuit.html.
This function should contains following parameters,otherwise it can not run properly in QuantumLayerV2.
Compare to QuantumLayer.you should allocate qubits and simulator: https://pyqpanda-toturial.readthedocs.io/zh/latest/QuantumMachine.html,
you may also need to allocate cbits if qprog_with_measure needs quantum measure: https://pyqpanda-toturial.readthedocs.io/zh/latest/Measure.html
qprog_with_measure (input,param)
input: array_like input 1-dim classic data
param: array_like input 1-dim quantum circuit’s parameters
Example:
import pyqpanda as pq from pyvqnet.qnn.measure import ProbsMeasure from pyvqnet.qnn.quantumlayer import QuantumLayerV2 import numpy as np from pyvqnet.tensor import QTensor def pqctest (input,param): num_of_qubits = 4 m_machine = pq.CPUQVM()# outside m_machine.init_qvm()# outside qubits = m_machine.qAlloc_many(num_of_qubits) circuit = pq.QCircuit() circuit.insert(pq.H(qubits[0])) circuit.insert(pq.H(qubits[1])) circuit.insert(pq.H(qubits[2])) circuit.insert(pq.H(qubits[3])) circuit.insert(pq.RZ(qubits[0],input[0])) circuit.insert(pq.RZ(qubits[1],input[1])) circuit.insert(pq.RZ(qubits[2],input[2])) circuit.insert(pq.RZ(qubits[3],input[3])) circuit.insert(pq.CNOT(qubits[0],qubits[1])) circuit.insert(pq.RZ(qubits[1],param[0])) circuit.insert(pq.CNOT(qubits[0],qubits[1])) circuit.insert(pq.CNOT(qubits[1],qubits[2])) circuit.insert(pq.RZ(qubits[2],param[1])) circuit.insert(pq.CNOT(qubits[1],qubits[2])) circuit.insert(pq.CNOT(qubits[2],qubits[3])) circuit.insert(pq.RZ(qubits[3],param[2])) circuit.insert(pq.CNOT(qubits[2],qubits[3])) #print(circuit) prog = pq.QProg() prog.insert(circuit) rlt_prob = ProbsMeasure([0,2],prog,m_machine,qubits) return rlt_prob pqc = QuantumLayerV2(pqctest,3) #classic data as input input = QTensor([[1,2,3,4],[4,2,2,3],[3,3,2,2.0]] ) #forward circuits rlt = pqc(input) grad = QTensor(np.ones(rlt.data.shape)*1000) #backward circuits rlt.backward(grad) print(rlt) # [ # [0.2500000, 0.2500000, 0.2500000, 0.2500000], # [0.2500000, 0.2500000, 0.2500000, 0.2500000], # [0.2500000, 0.2500000, 0.2500000, 0.2500000] # ]
QuantumBatchAsyncQcloudLayer¶
When you install the latest version of pyqpanda, you can use this interface to define a variational circuit and submit it to originqc for running on the real chip.
- class pyvqnet.qnn.quantumlayer.QuantumBatchAsyncQcloudLayer(origin_qprog_func, qcloud_token, para_num, num_qubits, num_cubits, pauli_str_dict=None, shots=1000, initializer=None, dtype=None, name='', diff_method='parameter_shift ', submit_kwargs={}, query_kwargs={})¶
Abstract computing module for originqc real chips using pyqpanda QCLOUD starting with version 3.8.2.2. It submits parameterized quantum circuits to real chips and obtains measurement results.
Note
qcloud_token is the API token you applied for at https://qcloud.originqc.com.cn/. origin_qprog_func needs to return data of type pypqanda.QProg. If pauli_str_dict is not set, you need to ensure that measure has been inserted into the QProg. The form of origin_qprog_func must be as follows:
origin_qprog_func(input,param,qubits,cbits,machine)
input: Input 1~2-dimensional classic data. In the case of two-dimensional data, the first dimension is the batch size.
param: Enter the parameters to be trained for the one-dimensional variational quantum circuit.
machine: The simulator QCloud created by QuantumBatchAsyncQcloudLayer does not require users to define it in additional functions.
qubits: Qubits created by the simulator QCloud created by QuantumBatchAsyncQcloudLayer, the number is num_qubits, the type is pyQpanda.Qubits, no need for the user to define it in the function.
cbits: Classic bits allocated by QuantumBatchAsyncQcloudLayer, the number is num_cubits, the type is pyQpanda.ClassicalCondition, no need for the user to define it in the function. .
- Parameters:
origin_qprog_func – The variational quantum circuit function built by QPanda must return QProg.
qcloud_token – str - The type of quantum machine or cloud token used for execution.
para_num – int - Number of parameters, the parameter is a QTensor of size [para_num].
num_qubits – int - Number of qubits in the quantum circuit.
num_cubits – int - The number of classical bits used for measurement in quantum circuits.
pauli_str_dict – dict|list - A dictionary or list of dictionaries representing Pauli operators in quantum circuits. The default is “none”, and the measurement operation is performed. If a dictionary of Pauli operators is entered, a single expectation or multiple expectations will be calculated.
shot – int - Number of measurements. The default value is 1000.
initializer – Initializer for parameter values. The default is “None”, using 0~2*pi normal distribution.
dtype – The data type of the parameter. The default value is None, which uses the default data type pyvqnet.kfloat32.
name – The name of the module. Defaults to empty string.
diff_method – Differential method for gradient calculation. The default is “parameter_shift”, other differential methods are not currently supported.
Submit_kwargs – Additional keyword parameters used to submit quantum circuits, reserved parameters, currently have no effect.
query_kwargs – Additional keyword parameters used to query quantum results, reserved parameters, currently have no effect.
- Returns:
A module that can calculate quantum circuits.
Example:
import numpy as np import pyqpanda as pq import pyvqnet from pyvqnet.qnn import QuantumLayer,QuantumBatchAsyncQcloudLayer from pyvqnet.qnn import expval_qcloud #set_test_qcloud_fake(False) #uncomments this code to use realchip def qfun(input,param, m_machine, m_qlist,cubits): measure_qubits = [0,2] m_prog = pq.QProg() cir = pq.QCircuit() cir.insert(pq.RZ(m_qlist[0],input[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[1])) cir.insert(pq.RY(m_qlist[1],param[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[2])) cir.insert(pq.RZ(m_qlist[1],input[1])) cir.insert(pq.RY(m_qlist[2],param[1])) cir.insert(pq.H(m_qlist[2])) m_prog.insert(cir) for idx, ele in enumerate(measure_qubits): m_prog << pq.Measure(m_qlist[ele], cubits[idx]) # pylint: disable=expression-not-assigned return m_prog l = QuantumBatchAsyncQcloudLayer(qfun, "3047DE8A59764BEDAC9C3282093B16AF1", 2, 6, 6, pauli_str_dict=None, shots = 1000, initializer=None, dtype=None, name="", diff_method="parameter_shift", submit_kwargs={}, query_kwargs={}) x = pyvqnet.tensor.QTensor([[0.56,1.2],[0.56,1.2],[0.56,1.2],[0.56,1.2],[0.56,1.2]],requires_grad= True) y = l(x) print(y) y.backward() print(l.m_para.grad) print(x.grad) def qfun2(input,param, m_machine, m_qlist,cubits): measure_qubits = [0,2] m_prog = pq.QProg() cir = pq.QCircuit() cir.insert(pq.RZ(m_qlist[0],input[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[1])) cir.insert(pq.RY(m_qlist[1],param[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[2])) cir.insert(pq.RZ(m_qlist[1],input[1])) cir.insert(pq.RY(m_qlist[2],param[1])) cir.insert(pq.H(m_qlist[2])) m_prog.insert(cir) return m_prog l = QuantumBatchAsyncQcloudLayer(qfun2, "3047DE8A59764BEDAC9C3282093B16AF", 2, 6, 6, pauli_str_dict={'Z0 X1':10,'':-0.5,'Y2':-0.543}, shots = 1000, initializer=None, dtype=None, name="", diff_method="parameter_shift", submit_kwargs={}, query_kwargs={}) x = pyvqnet.tensor.QTensor([[0.56,1.2],[0.56,1.2],[0.56,1.2],[0.56,1.2]],requires_grad= True) y = l(x) print(y) y.backward() print(l.m_para.grad) print(x.grad)
QuantumLayerMultiProcess¶
If you are more familiar with pyQPanda syntax, please using QuantumLayerMultiProcess class, you can define the quantum circuits function by using qubits
, cbits
and machine
, then take it as a argument qprog_with_measure
of QuantumLayerMultiProcess.
- class pyvqnet.qnn.quantumlayer.QuantumLayerMultiProcess(qprog_with_measure, para_num, machine_type_or_cloud_token, num_of_qubits: int, num_of_cbits: int = 1, diff_method: str = 'parameter_shift', delta: float = 0.01, dtype=None, name='')¶
Abstract calculation module for variational quantum circuits. This class uses multiprocess to accelerate quantum circuit simulation.
It simulates a parameterized quantum circuit and gets the measurement result. QuantumLayer inherits from Module ,so that it can calculate gradients of circuits parameters,and train variational quantum circuits model or embed variational quantum circuits into hybird quantum and classic model.
To use this module, you need to create your quantum virtual machine and allocate qubits and cbits.
- Parameters:
qprog_with_measure – callable quantum circuits functions ,cosntructed by qpanda.
para_num – int - Number of parameter
num_of_qubits – num of qubits.
num_of_cbits – num of classic bits.
diff_method – ‘parameter_shift’ or ‘finite_diff’.
delta – delta for diff.
dtype – The data type of the parameter, defaults: None, use the default data type kfloat32, which represents a 32-bit floating point number.
name – name of the output layer
- Returns:
a module can calculate quantum circuits .
Note
qprog_with_measure is quantum circuits function defined in pyQPanda : https://github.com/OriginQ/QPanda-2.
This function should contains following parameters,otherwise it can not run properly in QuantumLayerMultiProcess.
Compare to QuantumLayer.you should allocate qubits and simulator,
you may also need to allocate cbits if qprog_with_measure needs quantum Measure.
qprog_with_measure (input,param)
input: array_like input 1-dim classic data
param: array_like input 1-dim quantum circuit’s parameters
Example:
import pyqpanda as pq from pyvqnet.qnn.measure import ProbsMeasure from pyvqnet.qnn.quantumlayer import QuantumLayerMultiProcess import numpy as np from pyvqnet.tensor import QTensor def pqctest (input,param,nqubits,ncubits): machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(nqubits) circuit = pq.QCircuit() circuit.insert(pq.H(qubits[0])) circuit.insert(pq.H(qubits[1])) circuit.insert(pq.H(qubits[2])) circuit.insert(pq.H(qubits[3])) circuit.insert(pq.RZ(qubits[0],input[0])) circuit.insert(pq.RZ(qubits[1],input[1])) circuit.insert(pq.RZ(qubits[2],input[2])) circuit.insert(pq.RZ(qubits[3],input[3])) circuit.insert(pq.CNOT(qubits[0],qubits[1])) circuit.insert(pq.RZ(qubits[1],param[0])) circuit.insert(pq.CNOT(qubits[0],qubits[1])) circuit.insert(pq.CNOT(qubits[1],qubits[2])) circuit.insert(pq.RZ(qubits[2],param[1])) circuit.insert(pq.CNOT(qubits[1],qubits[2])) circuit.insert(pq.CNOT(qubits[2],qubits[3])) circuit.insert(pq.RZ(qubits[3],param[2])) circuit.insert(pq.CNOT(qubits[2],qubits[3])) prog = pq.QProg() prog.insert(circuit) rlt_prob = ProbsMeasure([0,2],prog,machine,qubits) return rlt_prob pqc = QuantumLayerMultiProcess(pqctest,3,4,1) #classic data as input input = QTensor([[1.0,2,3,4],[4,2,2,3],[3,3,2,2]] ) #forward circuits rlt = pqc(input) grad = QTensor(np.ones(rlt.data.shape)*1000) #backward circuits rlt.backward(grad) print(rlt) # [ # [0.2500000, 0.2500000, 0.2500000, 0.2500000], # [0.2500000, 0.2500000, 0.2500000, 0.2500000], # [0.2500000, 0.2500000, 0.2500000, 0.2500000] # ]
NoiseQuantumLayer¶
In the real quantum computer, due to the physical characteristics of the quantum bit, there is always inevitable calculation error. In order to better simulate this error in quantum virtual machine, VQNet also supports quantum virtual machine with noise. The simulation of quantum virtual machine with noise is closer to the real quantum computer. We can customize the supported logic gate type and the noise model supported by the logic gate. The existing supported quantum noise model is defined in QPanda NoiseQVM .
We can use NoiseQuantumLayer
to define an automatic microclassification of quantum circuits. NoiseQuantumLayer
supports QPanda quantum virtual machine with noise. You can define a function as an argument qprog_with_measure
. This function needs to contain the quantum circuit defined by pyQPanda, as also you need to pass in a argument noise_set_config
, by using the pyQPanda interface to set up the noise model.
- class pyvqnet.qnn.quantumlayer.NoiseQuantumLayer(qprog_with_measure, para_num, machine_type, num_of_qubits: int, num_of_cbits: int = 1, diff_method: str = 'parameter_shift', delta: float = 0.01, noise_set_config=None, dtype=None, name='')¶
Abstract calculation module for variational quantum circuits. It simulates a parameterized quantum circuit and gets the measurement result. QuantumLayer inherits from Module ,so that it can calculate gradients of circuits parameters,and train variational quantum circuits model or embed variational quantum circuits into hybird quantum and classic model.
This module should be initialized with noise model by
noise_set_config
.- Parameters:
qprog_with_measure – callable quantum circuits functions ,cosntructed by qpanda
para_num – int - Number of para_num
machine_type – qpanda machine type
num_of_qubits – num of qubits
num_of_cbits – num of cbits
diff_method – ‘parameter_shift’ or ‘finite_diff’
delta – delta for diff
noise_set_config – noise set function
dtype – The data type of the parameter, defaults: None, use the default data type kfloat32, which represents a 32-bit floating point number.
name – name of the output layer
- Returns:
a module can calculate quantum circuits with noise model.
Note
qprog_with_measure is quantum circuits function defined in pyQPanda :https://pyqpanda-toturial.readthedocs.io/zh/latest/QCircuit.html.
This function should contains following parameters,otherwise it can not run properly in NoiseQuantumLayer.
qprog_with_measure (input,param,qubits,cbits,m_machine)
input: array_like input 1-dim classic data
param: array_like input 1-dim quantum circuit’s parameters
qubits: qubits allocated by NoiseQuantumLayer
cbits: cbits allocated by NoiseQuantumLayer.if your circuits does not use cbits,you should also reserve this parameter.
m_machine: simulator created by NoiseQuantumLayer
Example:
import pyqpanda as pq from pyvqnet.qnn.measure import ProbsMeasure from pyvqnet.qnn.quantumlayer import NoiseQuantumLayer import numpy as np from pyqpanda import * from pyvqnet.tensor import QTensor def circuit(weights, param, qubits, cbits, machine): circuit = pq.QCircuit() circuit.insert(pq.H(qubits[0])) circuit.insert(pq.RY(qubits[0], weights[0])) circuit.insert(pq.RY(qubits[0], param[0])) prog = pq.QProg() prog.insert(circuit) prog << measure_all(qubits, cbits) result = machine.run_with_configuration(prog, cbits, 100) counts = np.array(list(result.values())) states = np.array(list(result.keys())).astype(float) # Compute probabilities for each state probabilities = counts / 100 # Get state expectation expectation = np.sum(states * probabilities) return expectation def default_noise_config(qvm, q): p = 0.01 qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.PAULI_X_GATE, p) qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.PAULI_Y_GATE, p) qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.PAULI_Z_GATE, p) qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RX_GATE, p) qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RY_GATE, p) qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RZ_GATE, p) qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RY_GATE, p) qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.HADAMARD_GATE, p) qves = [] for i in range(len(q) - 1): qves.append([q[i], q[i + 1]]) # qves.append([q[len(q) - 1], q[0]]) qvm.set_noise_model(NoiseModel.DAMPING_KRAUS_OPERATOR, GateType.CNOT_GATE, p, qves) return qvm qvc = NoiseQuantumLayer(circuit, 24, "noise", 1, 1, diff_method="parameter_shift", delta=0.01, noise_set_config=default_noise_config) input = QTensor([[0., 1., 1., 1.], [0., 0., 1., 1.], [1., 0., 1., 1.]]) rlt = qvc(input) grad = QTensor(np.ones(rlt.data.shape) * 1000) rlt.backward(grad) print(qvc.m_para.grad) #[1195., 105., 70., 0., # 45., -45., 50., 15., # -80., 50., 10., -30., # 10., 60., 75., -110., # 55., 45., 25., 5., # 5., 50., -25., -15.]
Here is an example of noise_set_config
, here we add the noise model BITFLIP_KRAUS_OPERATOR where the noise argument p=0.01 to the quantum gate RX
, RY
, RZ
, X
, Y
, Z
, H
, etc.
def noise_set_config(qvm,q):
p = 0.01
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.PAULI_X_GATE, p)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.PAULI_Y_GATE, p)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.PAULI_Z_GATE, p)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RX_GATE, p)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RY_GATE, p)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RZ_GATE, p)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.RY_GATE, p)
qvm.set_noise_model(NoiseModel.BITFLIP_KRAUS_OPERATOR, GateType.HADAMARD_GATE, p)
qves =[]
for i in range(len(q)-1):
qves.append([q[i],q[i+1]])#
qves.append([q[len(q)-1],q[0]])
qvm.set_noise_model(NoiseModel.DAMPING_KRAUS_OPERATOR, GateType.CNOT_GATE, p, qves)
return qvm
VQCLayer¶
Based on the variable quantum circuit(VariationalQuantumCircuit) of pyQPanda, VQNet provides an abstract quantum computing layer called VQCLayer
.
You just only needs to define a class that inherits from VQC_wrapper
, and construct quantum gates of circuits and measurement functions based on pyQPanda VariationalQuantumCircuit
in it.
In VQC_wrapper
, you can use the common logic gate function build_common_circuits
to build a sub-circuits of the model with variable circuit’s structure, use the VQG in build_vqc_circuits
to build sub-circuits with constant structure and variable parameters,
use the run
function to define the circuit operations and measurement.
- class pyvqnet.qnn.quantumlayer.VQC_wrapper¶
VQC_wrapper
is a abstract class help to run VariationalQuantumCircuit on VQNet.build_common_circuits
function contains circuits may be varaible according to the input.build_vqc_circuits
function contains VQC circuits with trainable weights.run
function contains run function for VQC.Example:
import pyqpanda as pq from pyqpanda import * from pyvqnet.qnn.quantumlayer import VQCLayer,VQC_wrapper class QVC_demo(VQC_wrapper): def __init__(self): super(QVC_demo, self).__init__() def build_common_circuits(self,input,qlists,): qc = pq.QCircuit() for i in range(len(qlists)): if input[i]==1: qc.insert(pq.X(qlists[i])) return qc def build_vqc_circuits(self,input,weights,machine,qlists,clists): def get_cnot(qubits): vqc = VariationalQuantumCircuit() for i in range(len(qubits)-1): vqc.insert(pq.VariationalQuantumGate_CNOT(qubits[i],qubits[i+1])) vqc.insert(pq.VariationalQuantumGate_CNOT(qubits[len(qubits)-1],qubits[0])) return vqc def build_circult(weights, xx, qubits,vqc): def Rot(weights_j, qubits): vqc = VariationalQuantumCircuit() vqc.insert(pq.VariationalQuantumGate_RZ(qubits, weights_j[0])) vqc.insert(pq.VariationalQuantumGate_RY(qubits, weights_j[1])) vqc.insert(pq.VariationalQuantumGate_RZ(qubits, weights_j[2])) return vqc #2,4,3 for i in range(2): weights_i = weights[i,:,:] for j in range(len(qubits)): weights_j = weights_i[j] vqc.insert(Rot(weights_j,qubits[j])) cnots = get_cnot(qubits) vqc.insert(cnots) vqc.insert(pq.VariationalQuantumGate_Z(qubits[0]))#pauli z(0) return vqc weights = weights.reshape([2,4,3]) vqc = VariationalQuantumCircuit() return build_circult(weights, input,qlists,vqc)
Send the instantiated object VQC_wrapper
as a parameter to VQCLayer
- class pyvqnet.qnn.quantumlayer.VQCLayer(vqc_wrapper, para_num, machine_type_or_cloud_token, num_of_qubits: int, num_of_cbits: int = 1, diff_method: str = 'parameter_shift', delta: float = 0.01, dtype=None, name='')¶
Abstract Calculation module for Variational Quantum Circuits in pyQPanda.Please reference to :https://pyqpanda-toturial.readthedocs.io/zh/latest/VQG.html.
- Parameters:
vqc_wrapper – VQC_wrapper class
para_num – int - Number of parameter
machine_type – qpanda machine type
num_of_qubits – num of qubits
num_of_cbits – num of cbits
diff_method – ‘parameter_shift’ or ‘finite_diff’
delta – delta for gradient calculation.
dtype – The data type of the parameter, defaults: None, use the default data type kfloat32, which represents a 32-bit floating point number.
name – name of the output layer
- Returns:
a module can calculate VQC quantum circuits
Example:
import pyqpanda as pq from pyqpanda import * from pyvqnet.qnn.quantumlayer import VQCLayer,VQC_wrapper class QVC_demo(VQC_wrapper): def __init__(self): super(QVC_demo, self).__init__() def build_common_circuits(self,input,qlists,): qc = pq.QCircuit() for i in range(len(qlists)): if input[i]==1: qc.insert(pq.X(qlists[i])) return qc def build_vqc_circuits(self,input,weights,machine,qlists,clists): def get_cnot(qubits): vqc = VariationalQuantumCircuit() for i in range(len(qubits)-1): vqc.insert(pq.VariationalQuantumGate_CNOT(qubits[i],qubits[i+1])) vqc.insert(pq.VariationalQuantumGate_CNOT(qubits[len(qubits)-1],qubits[0])) return vqc def build_circult(weights, xx, qubits,vqc): def Rot(weights_j, qubits): vqc = VariationalQuantumCircuit() vqc.insert(pq.VariationalQuantumGate_RZ(qubits, weights_j[0])) vqc.insert(pq.VariationalQuantumGate_RY(qubits, weights_j[1])) vqc.insert(pq.VariationalQuantumGate_RZ(qubits, weights_j[2])) return vqc #2,4,3 for i in range(2): weights_i = weights[i,:,:] for j in range(len(qubits)): weights_j = weights_i[j] vqc.insert(Rot(weights_j,qubits[j])) cnots = get_cnot(qubits) vqc.insert(cnots) vqc.insert(pq.VariationalQuantumGate_Z(qubits[0]))#pauli z(0) return vqc weights = weights.reshape([2,4,3]) vqc = VariationalQuantumCircuit() return build_circult(weights, input,qlists,vqc) def run(self,vqc,input,machine,qlists,clists): prog = QProg() vqc_all = VariationalQuantumCircuit() # add encode circuits vqc_all.insert(self.build_common_circuits(input,qlists)) vqc_all.insert(vqc) qcir = vqc_all.feed() prog.insert(qcir) #print(pq.convert_qprog_to_originir(prog, machine)) prob = machine.prob_run_dict(prog, qlists[0], -1) prob = list(prob.values()) return prob qvc_vqc = QVC_demo() VQCLayer(qvc_vqc,24,"cpu",4)
Qconv¶
Qconv is a quantum convolution algorithm interface. Quantum convolution operation adopts quantum circuit to carry out convolution operation on classical data, which does not need to calculate multiplication and addition operation, but only needs to encode data into quantum state, and then obtain the final convolution result through derivation operation and measurement of quantum circuit. Applies for the same number of quantum bits according to the number of input data in the range of the convolution kernel, and then construct a quantum circuit for calculation.
First we need encoding by inserting \(RY\) and \(RZ\) gates on each qubit, then, we constructed the parameter circuit through \(U3\) gate and \(Z\) gate . The sample is as follows:
- class pyvqnet.qnn.qcnn.qconv.QConv(input_channels, output_channels, quantum_number, stride=(1, 1), padding=(0, 0), kernel_initializer=normal, machine: str = 'cpu', dtype=None, name='')¶
Quantum Convolution module. Replace Conv2D kernal with quantum circuits.Inputs to the conv module are of shape (batch_size, input_channels, height, width) reference Samuel et al. (2020).
- Parameters:
input_channels – int - Number of input channels
output_channels – int - Number of kernels
quantum_number – int - Size of a single kernel.
stride – tuple - Stride, defaults to (1, 1)
padding – tuple - Padding, defaults to (0, 0)
kernel_initializer – callable - Defaults to normal
machine – str - cpu simulation.
dtype – The data type of the parameter, defaults: None, use the default data type kfloat32, which represents a 32-bit floating point number.
name – name of the output layer
- Returns:
a quantum cnn class
Example:
from pyvqnet.tensor import tensor from pyvqnet.qnn.qcnn.qconv import QConv x = tensor.ones([1,3,4,4]) layer = QConv(input_channels=3, output_channels=2, quantum_number=4, stride=(2, 2)) y = layer(x) print(y) # [ # [[[-0.0889078, -0.0889078], # [-0.0889078, -0.0889078]], # [[0.7992646, 0.7992646], # [0.7992646, 0.7992646]]] # ]
QLinear¶
QLinear implements a quantum full connection algorithm. Firstly, the data is encoded into the quantum state, and then the final fully connected result is obtained through the derivation operation and measurement of the quantum circuit.
- class pyvqnet.qnn.qlinear.QLinear(input_channels, output_channels, machine: str = 'cpu')¶
Quantum Linear module. Inputs to the linear module are of shape (input_channels, output_channels).This layer takes no variational quantum parameters.
- Parameters:
input_channels – int - Number of input channels
output_channels – int - Number of output channels
machine – str - cpu simulation
- Returns:
a quantum linear layer
Exmaple:
from pyvqnet.tensor import QTensor from pyvqnet.qnn.qlinear import QLinear params = [[0.37454012, 0.95071431, 0.73199394, 0.59865848, 0.15601864, 0.15599452], [1.37454012, 0.95071431, 0.73199394, 0.59865848, 0.15601864, 0.15599452], [1.37454012, 1.95071431, 0.73199394, 0.59865848, 0.15601864, 0.15599452], [1.37454012, 1.95071431, 1.73199394, 1.59865848, 0.15601864, 0.15599452]] m = QLinear(6, 2) input = QTensor(params, requires_grad=True) output = m(input) output.backward() print(output) # [ #[0.0568473, 0.1264389], #[0.1524036, 0.1264389], #[0.1524036, 0.1442845], #[0.1524036, 0.1442845] # ]
grad¶
- pyvqnet.qnn.quantumlayer.grad(quantum_prog_func, params *args)¶
The grad function provides an interface to compute the gradient of a user-designed subcircuit with parametric parameters. Users can use pyqpanda to design the line running function
quantum_prog_func
according to the following example, and send it as a parameter to the grad function. The second parameter of the grad function is the coordinates at which you want to calculate the gradient of the quantum logic gate parameters. The return value has shape [num of parameters,num of output].- Parameters:
quantum_prog_func – The quantum circuit operation function designed by pyqpanda.
params – The coordinates of the parameters whose gradient is to be obtained.
*args – additional arguments to the quantum_prog_func function.
- Returns:
gradient of parameters
Examples:
from pyvqnet.qnn import grad, ProbsMeasure import pyqpanda as pq def pqctest(param): machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(2) circuit = pq.QCircuit() circuit.insert(pq.RX(qubits[0], param[0])) circuit.insert(pq.RY(qubits[1], param[1])) circuit.insert(pq.CNOT(qubits[0], qubits[1])) circuit.insert(pq.RX(qubits[1], param[2])) prog = pq.QProg() prog.insert(circuit) EXP = ProbsMeasure([1],prog,machine,qubits) return EXP g = grad(pqctest, [0.1,0.2, 0.3]) print(g) # [[-0.04673668 0.04673668] # [-0.09442394 0.09442394] # [-0.14409127 0.14409127]]
Quantum Gates¶
The way to deal with qubits is called quantum gates. Using quantum gates, we consciously evolve quantum states. Quantum gates are the basis of quantum algorithms.
Basic quantum gates¶
In VQNet, we use each logic gate of pyQPanda developed by the original quantum to build quantum circuit and conduct quantum simulation. The gates currently supported by pyQPanda can be defined in pyQPanda’s quantum gate section. In addition, VQNet also encapsulates some quantum gate combinations commonly used in quantum machine learning.
BasicEmbeddingCircuit¶
- pyvqnet.qnn.template.BasicEmbeddingCircuit(input_feat, qlist)¶
Encodes n binary features into a basis state of n qubits.
For example, for
features=([0, 1, 1])
, the quantum system will be prepared in state \(|011 \rangle\).- Parameters:
input_feat – binary input of shape
(n)
qlist – qlist that the template acts on
- Returns:
quantum circuits
Example:
import numpy as np import pyqpanda as pq from pyvqnet.qnn.template import BasicEmbeddingCircuit input_feat = np.array([1,1,0]).reshape([3]) m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) qlist = m_machine.qAlloc_many(3) circuit = BasicEmbeddingCircuit(input_feat,qlist) print(circuit) # ┌─┐ # q_0: |0>─┤X├ # ├─┤ # q_1: |0>─┤X├ # └─┘
AngleEmbeddingCircuit¶
- pyvqnet.qnn.template.AngleEmbeddingCircuit(input_feat, qubits, rotation: str = 'X')¶
Encodes \(N\) features into the rotation angles of \(n\) qubits, where \(N \leq n\).
The rotations can be chosen as either : ‘X’ , ‘Y’ , ‘Z’, as defined by the
rotation
parameter:rotation='X'
uses the features as angles of RX rotationsrotation='Y'
uses the features as angles of RY rotationsrotation='Z'
uses the features as angles of RZ rotations
The length of
features
has to be smaller or equal to the number of qubits. If there are fewer entries infeatures
than qlists, the circuit does not Applies the remaining rotation gates.- Parameters:
input_feat – numpy array which represents paramters
qubits – qubits allocated by pyQPanda
rotation – use what rotation ,default ‘X’
- Returns:
quantum circuits
Example:
import numpy as np import pyqpanda as pq from pyvqnet.qnn.template import AngleEmbeddingCircuit m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_qlist = m_machine.qAlloc_many(2) m_clist = m_machine.cAlloc_many(2) m_prog = pq.QProg() input_feat = np.array([2.2, 1]) C = AngleEmbeddingCircuit(input_feat,m_qlist,'X') print(C) C = AngleEmbeddingCircuit(input_feat,m_qlist,'Y') print(C) C = AngleEmbeddingCircuit(input_feat,m_qlist,'Z') print(C) pq.destroy_quantum_machine(m_machine) # ┌────────────┐ # q_0: |0>─┤RX(2.200000)├ # ├────────────┤ # q_1: |0>─┤RX(1.000000)├ # └────────────┘ # ┌────────────┐ # q_0: |0>─┤RY(2.200000)├ # ├────────────┤ # q_1: |0>─┤RY(1.000000)├ # └────────────┘ # ┌────────────┐ # q_0: |0>─┤RZ(2.200000)├ # ├────────────┤ # q_1: |0>─┤RZ(1.000000)├ # └────────────┘
AmplitudeEmbeddingCircuit¶
- pyvqnet.qnn.template.AmplitudeEmbeddingCircuit(input_feat, qubits)¶
Encodes \(2^n\) features into the amplitude vector of \(n\) qubits. To represent a valid quantum state vector, the L2-norm of
features
must be one.- Parameters:
input_feat – numpy array which represents paramters
qubits – qubits allocated by pyQPanda
- Returns:
quantum circuits
Example:
import numpy as np import pyqpanda as pq from pyvqnet.qnn.template import AmplitudeEmbeddingCircuit input_feat = np.array([2.2, 1, 4.5, 3.7]) m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_qlist = m_machine.qAlloc_many(2) m_clist = m_machine.cAlloc_many(2) m_prog = pq.QProg() cir = AmplitudeEmbeddingCircuit(input_feat,m_qlist) print(cir) pq.destroy_quantum_machine(m_machine) # ┌────────────┐ ┌────────────┐ # q_0: |0>─────────────── ─── ┤RY(0.853255)├ ─── ┤RY(1.376290)├ # ┌────────────┐ ┌─┐ └──────┬─────┘ ┌─┐ └──────┬─────┘ # q_1: |0>─┤RY(2.355174)├ ┤X├ ───────■────── ┤X├ ───────■────── # └────────────┘ └─┘ └─┘
IQPEmbeddingCircuits¶
- pyvqnet.qnn.template.IQPEmbeddingCircuits(input_feat, qubits, trep: int = 1)¶
Encodes \(n\) features into \(n\) qubits using diagonal gates of an IQP circuit.
The embedding was proposed by Havlicek et al. (2018).
The basic IQP circuit can be repeated by specifying
n_repeats
.- Parameters:
input_feat – numpy array which represents paramters
qubits – qubits allocated by pyQPanda
rep – repeat circuits block
- Returns:
quantum circuits
Example:
import numpy as np import pyqpanda as pq from pyvqnet.qnn.template import IQPEmbeddingCircuits m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) input_feat = np.arange(1,100) qlist = m_machine.qAlloc_many(3) circuit = IQPEmbeddingCircuits(input_feat,qlist,rep = 1) print(circuit) # ┌─┐ ┌────────────┐ # q_0: |0>─┤H├ ┤RZ(1.000000)├ ───■── ────────────── ───■── ───■── ────────────── ───■── ────── ────────────── ────── # ├─┤ ├────────────┤ ┌──┴─┐ ┌────────────┐ ┌──┴─┐ │ │ # q_1: |0>─┤H├ ┤RZ(2.000000)├ ┤CNOT├ ┤RZ(2.000000)├ ┤CNOT├ ───┼── ────────────── ───┼── ───■── ────────────── ───■── # ├─┤ ├────────────┤ └────┘ └────────────┘ └────┘ ┌──┴─┐ ┌────────────┐ ┌──┴─┐ ┌──┴─┐ ┌────────────┐ ┌──┴─┐ # q_2: |0>─┤H├ ┤RZ(3.000000)├ ────── ────────────── ────── ┤CNOT├ ┤RZ(3.000000)├ ┤CNOT├ ┤CNOT├ ┤RZ(3.000000)├ ┤CNOT├ # └─┘ └────────────┘ └────┘ └────────────┘ └────┘ └────┘ └────────────┘ └────┘
RotCircuit¶
- pyvqnet.qnn.template.RotCircuit(para, qubits)¶
Arbitrary single qubit rotation.Number of qlist should be 1,and number of parameters should be 3
\[\begin{split}R(\phi,\theta,\omega) = RZ(\omega)RY(\theta)RZ(\phi)= \begin{bmatrix} e^{-i(\phi+\omega)/2}\cos(\theta/2) & -e^{i(\phi-\omega)/2}\sin(\theta/2) \\ e^{-i(\phi-\omega)/2}\sin(\theta/2) & e^{i(\phi+\omega)/2}\cos(\theta/2) \end{bmatrix}.\end{split}\]- Parameters:
para – numpy array which represents paramters [phi, theta, omega]
qubits – qubits allocated by pyQPanda,only accepted single qubits.
- Returns:
quantum circuits
Example:
import pyqpanda as pq import numpy as np from pyvqnet.tensor import QTensor from pyvqnet.qnn.template import RotCircuit m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_clist = m_machine.cAlloc_many(2) m_prog = pq.QProg() m_qlist = m_machine.qAlloc_many(1) param = np.array([3,4,5]) c = pyvqnet.qnn.template.RotCircuit(param,m_qlist) print(c) pq.destroy_quantum_machine(m_machine) # ┌────────────┐ ┌────────────┐ ┌────────────┐ # q_0: |0>─┤RZ(5.000000)├ ┤RY(4.000000)├ ┤RZ(3.000000)├ # └────────────┘ └────────────┘ └────────────┘
CRotCircuit¶
- pyvqnet.qnn.template.CRotCircuit(para, control_qubits, rot_qubits)¶
The controlled-Rot operator
\[\begin{split}CR(\phi, \theta, \omega) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & e^{-i(\phi+\omega)/2}\cos(\theta/2) & -e^{i(\phi-\omega)/2}\sin(\theta/2)\\ 0 & 0 & e^{-i(\phi-\omega)/2}\sin(\theta/2) & e^{i(\phi+\omega)/2}\cos(\theta/2) \end{bmatrix}.\end{split}\]- Parameters:
para – numpy array which represents paramters [phi, theta, omega]
control_qubits – control qubit allocated by pyQPanda
rot_qubits – Rot qubit allocated by pyQPanda
- Returns:
quantum circuits
Example:
import numpy as np import pyqpanda as pq from pyvqnet.tensor import QTensor from pyvqnet.qnn.template import CRotCircuit m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_clist = m_machine.cAlloc_many(2) m_prog = pq.QProg() m_qlist = m_machine.qAlloc_many(1) param = np.array([3,4,5]) control_qlist = m_machine.qAlloc_many(1) c = CRotCircuit(QTensor(param),control_qlist,m_qlist) print(c) pq.destroy_quantum_machine(m_machine) # ┌────────────┐ ┌────────────┐ ┌────────────┐ # q_0: |0>─┤RZ(5.000000)├ ┤RY(4.000000)├ ┤RZ(3.000000)├ # └──────┬─────┘ └──────┬─────┘ └──────┬─────┘ # q_1: |0>────────■────── ───────■────── ───────■──────
CSWAPcircuit¶
- pyvqnet.qnn.template.CSWAPcircuit(qubits)¶
The controlled-swap circuit
\[\begin{split}CSWAP = \begin{bmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{bmatrix}.\end{split}\]Note
The first qubits provided corresponds to the control qubit.
- Parameters:
qubits – list of qubits allocated by pyQPanda the first qubits is control qubit. length of qlists have to be 3.
- Returns:
quantum circuits
Example:
from pyvqnet.qnn.template import CSWAPcircuit import pyqpanda as pq m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_qlist = m_machine.qAlloc_many(3) c = CSWAPcircuit([m_qlist[1],m_qlist[2],m_qlist[0]]) print(c) pq.destroy_quantum_machine(m_machine) # q_0: |0>─X─ # │ # q_1: |0>─■─ # │ # q_2: |0>─X─
Controlled_Hadamard¶
- pyvqnet.qnn.template.Controlled_Hadamard(qubits)¶
Controlled Hadamard logic gates.
\[\begin{split}CH = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ 0 & 0 & \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \end{bmatrix}.\end{split}\]- Parameters:
qubits – Qubits requested using pyqpanda.
Examples:
import pyqpanda as pq machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(2) from pyvqnet.qnn import Controlled_Hadamard cir = Controlled_Hadamard(qubits) print(cir) # q_0: |0>──────────────── ──■─ ────────────── # ┌─────────────┐ ┌─┴┐ ┌────────────┐ # q_1: |0>─┤RY(-0.785398)├ ┤CZ├ ┤RY(0.785398)├ # └─────────────┘ └──┘ └────────────┘
CCZ¶
- pyvqnet.qnn.template.CCZ(qubits)¶
Controlled-controlled-Z (controlled-controlled-Z) logic gate.
\[\begin{split}CCZ = \begin{pmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 \end{pmatrix}\end{split}\]- Parameters:
qubits – Qubits requested using pyqpanda.
- Returns:
pyqpanda QCircuit
Example:
import pyqpanda as pq machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(3) from pyvqnet.qnn import CCZ cir = CCZ(qubits) print(cir) # q_0: |0>─────── ─────── ───■── ─── ────── ─────── ───■── ───■── ┤T├──── ───■── # │ ┌─┐ │ ┌──┴─┐ ├─┴───┐ ┌──┴─┐ # q_1: |0>────■── ─────── ───┼── ─── ───■── ┤T├──── ───┼── ┤CNOT├ ┤T.dag├ ┤CNOT├ # ┌──┴─┐ ┌─────┐ ┌──┴─┐ ┌─┐ ┌──┴─┐ ├─┴───┐ ┌──┴─┐ ├─┬──┘ ├─┬───┘ ├─┬──┘ # q_2: |0>─┤CNOT├ ┤T.dag├ ┤CNOT├ ┤T├ ┤CNOT├ ┤T.dag├ ┤CNOT├ ┤T├─── ┤H├──── ┤H├─── # └────┘ └─────┘ └────┘ └─┘ └────┘ └─────┘ └────┘ └─┘ └─┘ └─┘
BlockEncode¶
- pyvqnet.qnn.template.BlockEncode(A, qlists)¶
Construct a single pyqpanda circuit \(U(A)\) such that an arbitrary matrix \(A\) is encoded in the top left block.
- Parameters:
A – The input matrix encoded in the circuit.
qlists – List of qubits to encode.
- Returns:
A pyqpanda QCircuit.
Example:
from pyvqnet.tensor import QTensor import pyvqnet import pyqpanda as pq from pyvqnet.qnn import BlockEncode A = QTensor([[0.1, 0.2], [0.3, 0.4]], dtype=pyvqnet.kfloat32) machine = pq.CPUQVM() machine.init_qvm() qlist = machine.qAlloc_many(2) cbits = machine.cAlloc_many(2) cir = BlockEncode(A, qlist) prog = pq.QProg() prog.insert(cir) result = machine.directly_run(prog) print(cir) # ┌───────────┐ # q_0: |0>─┤0 ├ # │ Unitary │ # q_1: |0>─┤1 ├ # └───────────┘
Random_Init_Quantum_State¶
- pyvqnet.qnn.template.Random_Init_Quantum_State(qlists)¶
Use amplitude encoding to generate arbitrary quantum initial states and encode them onto the wire. Note that the depth of the line can vary greatly due to amplitude encoding.
- Parameters:
qlists – Qubits requested by pyqpanda.
- Returns:
pyqpanda QCircuit.
Example:
import pyqpanda as pq from pyvqnet.qnn.template import Random_Init_Quantum_State cir = pq. QCircuit() m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_qlist = m_machine.qAlloc_many(3) c = Random_Init_Quantum_State(m_qlist) print(c) import pyqpanda as pq from pyvqnet.qnn.template import Random_Init_Quantum_State cir = pq.QCircuit() m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_qlist = m_machine.qAlloc_many(3) c = Random_Init_Quantum_State(m_qlist) print(c) # q_0: |0>─────────────── ─── ────────────── ─── ┤RY(0.583047)├ ─── ┤RY(0.176308)├ ─── ────────────── > # ┌────────────┐ ┌─┐ └──────┬─────┘ ┌─┐ └──────┬─────┘ ┌────────────┐ > # q_1: |0>─────────────── ─── ┤RY(1.062034)├ ┤X├ ───────■────── ┤X├ ───────■────── ─── ┤RY(1.724022)├ > # ┌────────────┐ ┌─┐ └──────┬─────┘ └┬┘ │ └┬┘ │ ┌─┐ └──────┬─────┘ > # q_2: |0>─┤RY(1.951150)├ ┤X├ ───────■────── ─■─ ───────■────── ─■─ ───────■────── ┤X├ ───────■────── > # └────────────┘ └─┘ └─┘ > # ┌────────────┐ ┌────────────┐ # q_0: |0>─── ┤RY(1.251911)├ ─── ┤RY(1.389063)├ # ┌─┐ └──────┬─────┘ ┌─┐ └──────┬─────┘ # q_1: |0>┤X├ ───────■────── ┤X├ ───────■────── # └┬┘ │ └┬┘ │ # q_2: |0>─■─ ───────■────── ─■─ ───────■──────
FermionicSingleExcitation¶
- pyvqnet.qnn.template.FermionicSingleExcitation(weight, wires, qubits)¶
A coupled cluster single-excitation operator for exponentiating the tensor product of a Pauli matrix. The matrix form is given by:
\[\hat{U}_{pr}(\theta) = \mathrm{exp} \{ \theta_{pr} (\hat{c}_p^\dagger \hat{c}_r -\mathrm{H.c.}) \}\]- Parameters:
weight – Variable parameter on qubit p.
wires – Indicates a subset of qubit indices in the interval [r, p]. Minimum length must be 2. The first index value is interpreted as r and the last index value as p. The intermediate index is acted on by the CNOT gate to calculate the parity of the qubit set.
qubits – Qubits applied by pyqpanda.
Examples:
from pyvqnet.qnn import FermionicSingleExcitation, expval weight = 0.5 import pyqpanda as pq machine = pq.CPUQVM() machine.init_qvm() qlists = machine.qAlloc_many(3) cir = FermionicSingleExcitation(weight, [1, 0, 2], qlists) prog = pq.QProg() prog.insert(cir) pauli_dict = {'Z0': 1} exp2 = expval(machine, prog, pauli_dict, qlists) print(f"vqnet {exp2}") #vqnet 1000000013
FermionicDoubleExcitation¶
- pyvqnet.qnn.template.FermionicDoubleExcitation(weight, wires1, wires2, qubits)¶
The coupled clustering dual excitation operator that exponentiates the tensor product of the Pauli matrix, the matrix form is given by:
\[\hat{U}_{pqrs}(\theta) = \mathrm{exp} \{ \theta (\hat{c}_p^\dagger \hat{c}_q^\dagger \hat{c}_r \hat{c}_s - \mathrm{H.c.}) \}\]where \(\hat{c}\) and \(\hat{c}^\dagger\) are the fermion annihilation and Create operators and indices \(r, s\) and \(p, q\) in the occupied and are empty molecular orbitals, respectively. Use the Jordan-Wigner transformation The fermion operator defined above can be written as According to the Pauli matrix (for more details, see arXiv:1805.04340)
\[\begin{split}\hat{U}_{pqrs}(\theta) = \mathrm{exp} \Big\{ \frac{i\theta}{8} \bigotimes_{b=s+1}^{r-1} \hat{Z}_b \bigotimes_{a=q+1}^{p-1} \hat{Z}_a (\hat{X}_s \hat{X}_r \hat{Y}_q \hat{X}_p + \hat{Y}_s \hat{X}_r \hat{Y}_q \hat{Y}_p +\\ \hat{X}_s \hat{Y}_r \hat{Y}_q \hat{Y}_p + \hat{X}_s \hat{X}_r \hat{X}_q \hat{Y}_p - \mathrm{H.c.} ) \Big\}\end{split}\]- Parameters:
weight – variable parameter
wires1 – The index list of the represented qubits occupies a subset of qubits in the interval [s, r]. The first index is interpreted as s, the last as r. CNOT gates operate on intermediate indices to compute the parity of a set of qubits.
wires2 – The index list of the represented qubits occupies a subset of qubits in the interval [q, p]. The first index is interpreted as q, the last as p. CNOT gates operate on intermediate indices to compute the parity of a set of qubits.
qubits – Qubits applied by pyqpanda.
- Returns:
pyqpanda QCircuit
Examples:
import pyqpanda as pq from pyvqnet.qnn import FermionicDoubleExcitation, expval machine = pq.CPUQVM() machine.init_qvm() qlists = machine.qAlloc_many(5) weight = 1.5 cir = FermionicDoubleExcitation(weight, wires1=[0, 1], wires2=[2, 3, 4], qubits=qlists) prog = pq.QProg() prog.insert(cir) pauli_dict = {'Z0': 1} exp2 = expval(machine, prog, pauli_dict, qlists) print(f"vqnet {exp2}") #vqnet 1000000058
UCCSD¶
- pyvqnet.qnn.template.UCCSD(weights, wires, s_wires, d_wires, init_state, qubits)¶
Realize the unitary coupled cluster single-excitation and double-excitation design (UCCSD). UCCSD is the proposed VQE design, commonly used to run quantum chemistry simulations.
Within the first-order Trotter approximation, the UCCSD unitary function is given by:
\[\hat{U}(\vec{\theta}) = \prod_{p > r} \mathrm{exp} \Big\{\theta_{pr} (\hat{c}_p^\dagger \hat{c}_r-\mathrm{H.c.}) \Big\} \prod_{p > q > r > s} \mathrm{exp} \Big\{\theta_{pqrs} (\hat{c}_p^\dagger \hat{c}_q^\dagger \hat{c}_r \hat{c}_s-\mathrm{H.c.}) \Big\}\]where \(\hat{c}\) and \(\hat{c}^\dagger\) are the fermion annihilation and Create operators and indices \(r, s\) and \(p, q\) in the occupied and are empty molecular orbitals, respectively. (For more details see arXiv:1805.04340):
- Parameters:
weights –
(len(s_wires)+ len(d_wires))
tensor containing the size of the parameters \(\theta_{pr}\) and \(\theta_{pqrs}\) input Z rotationFermionicSingleExcitation
andFermionicDoubleExcitation
.wires – qubit index for template action
s_wires – sequence of lists containing qubit indices
[r,...,p]
produced by a single excitation \(\vert r, p \rangle = \hat{c}_p^\dagger \hat{c}_r \vert \mathrm{HF} \rangle\), where \(\vert \mathrm{HF} \rangle\) denotes the Hartee-Fock reference state.d_wires – list sequence, each list contains two lists specify indices
[s, ...,r]
and[q,...,p]
Define double excitation \(\vert s, r, q, p \rangle = \hat{c}_p^\dagger \hat{c}_q^\dagger \hat{c}_r\hat{c}_s \ vert \mathrm{HF} \rangle\).init_state – length
len(wires)
occupation-number vector representation high frequency state.init_state
is the qubit initialization state.qubits – Qubits allocated by pyqpanda.
Examples:
import pyqpanda as pq from pyvqnet.tensor import tensor from pyvqnet.qnn import UCCSD, expval machine = pq.CPUQVM() machine.init_qvm() qlists = machine.qAlloc_many(6) weight = tensor.zeros([8]) cir = UCCSD(weight,wires = [0,1,2,3,4,5,6], s_wires=[[0, 1, 2], [0, 1, 2, 3, 4], [1, 2, 3], [1, 2, 3, 4, 5]], d_wires=[[[0, 1], [2, 3]], [[0, 1], [2, 3, 4, 5]], [[0, 1], [3, 4]], [[0, 1], [4, 5]]], init_state=[1, 1, 0, 0, 0, 0], qubits=qlists) prog = pq.QProg() prog.insert(cir) pauli_dict = {'Z0': 1} exp2 = expval(machine, prog, pauli_dict, qlists) print(f"vqnet {exp2}") #vqnet -1000000004
QuantumPoolingCircuit¶
- pyvqnet.qnn.template.QuantumPoolingCircuit(sources_wires, sinks_wires, params, qubits)¶
A quantum circuit that downsamples data. To reduce the number of qubits in our circuit, we first create pairs of qubits in our system. After initially pairing all qubits, we apply our generalized 2-qubit unitary to each pair. After applying the two-qubit unitary, we ignore one qubit in each pair of qubits for the rest of the neural network.
- Parameters:
sources_wires – Source qubit indices that will be ignored.
sinks_wires – Destination qubit indices that will be kept.
params – Input parameters.
qubits – list of qubits allocated by pyqpanda.
- Returns:
pyqpanda QCircuit
Examples:
from pyvqnet.qnn import QuantumPoolingCircuit import pyqpanda as pq from pyvqnet import tensor machine = pq.CPUQVM() machine.init_qvm() qlists = machine.qAlloc_many(4) p = tensor.full([6], 0.35) cir = QuantumPoolingCircuit([0, 1], [2, 3], p, qlists) print(cir) # ┌────┐ ┌────────────┐ ! # > # q_0: |0>──────────────── ┤CNOT├ ┤RZ(0.350000)├ ───■── ────────────── ────! ─────────────── ────── ────────────── # > # └──┬─┘ └────────────┘ │ ! ┌────┐ ┌────────────┐ # > # q_1: |0>──────────────── ───┼── ────────────── ───┼── ────────────── ────! ─────────────── ┤CNOT├ ┤RZ(0.350000)├ # > # ┌─────────────┐ │ ┌────────────┐ ┌──┴─┐ ┌────────────┐ ! └──┬─┘ └────────────┘ # > # q_2: |0>─┤RZ(-1.570796)├ ───■── ┤RY(0.350000)├ ┤CNOT├ ┤RY(0.350000)├ ────! ─────────────── ───┼── ────────────── # > # └─────────────┘ └────────────┘ └────┘ └────────────┘ ! ┌─────────────┐ │ ┌────────────┐ # > # q_3: |0>──────────────── ────── ────────────── ────── ────────────── ────! ┤RZ(-1.570796)├ ───■── ┤RY(0.350000)├ # > # ! └─────────────┘ └────────────┘ # > # ! # q_0: |0>────── ────────────── ────! # ! # q_1: |0>───■── ────────────── ────! # │ ! # q_2: |0>───┼── ────────────── ────! # ┌──┴─┐ ┌────────────┐ ! # q_3: |0>┤CNOT├ ┤RY(0.350000)├ ────!
Commonly used quantum circuits¶
VQNet provides some quantum circuits commonly used in quantum machine learning research.
HardwareEfficientAnsatz¶
- class pyvqnet.qnn.ansatz.HardwareEfficientAnsatz(n_qubits, single_rot_gate_list, qubits, entangle_gate='CNOT', entangle_rules='linear', depth=1)¶
The implementation of Hardware Efficient Ansatz introduced in the paper: Hardware-efficient Variational Quantum Eigensolver for Small Molecules.
- Parameters:
n_qubits – Number of qubits.
single_rot_gate_list – A single qubit rotation gate list is constructed by one or several rotation gate that act on every qubit.Currently support Rx, Ry, Rz.
qubits – Qubits allocated by pyqpanda api.
entangle_gate – The non parameterized entanglement gate.CNOT,CZ is supported.default:CNOT.
entangle_rules – How entanglement gate is used in the circuit.
linear
means the entanglement gate will be act on every neighboring qubits.all
means the entanglment gate will be act on any two qbuits. Default:linear
.depth – The depth of ansatz, default:1.
Example:
import pyqpanda as pq from pyvqnet.tensor import QTensor,tensor from pyvqnet.qnn import HardwareEfficientAnsatz machine = pq.CPUQVM() machine.init_qvm() qlist = machine.qAlloc_many(4) c = HardwareEfficientAnsatz(4, ["rx", "RY", "rz"], qlist, entangle_gate="cnot", entangle_rules="linear", depth=1) w = tensor.ones([c.get_para_num()]) cir = c.create_ansatz(w) print(cir) # ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ # q_0: |0>─┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ ───■── ┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ ────────────── ────────────── # ├────────────┤ ├────────────┤ ├────────────┤ ┌──┴─┐ └────────────┘ ├────────────┤ ├────────────┤ ┌────────────┐ # q_1: |0>─┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ ┤CNOT├ ───■────────── ┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ ────────────── # ├────────────┤ ├────────────┤ ├────────────┤ └────┘ ┌──┴─┐ └────────────┘ ├────────────┤ ├────────────┤ ┌────────────┐ # q_2: |0>─┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ ────── ┤CNOT├──────── ───■────────── ┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ # ├────────────┤ ├────────────┤ ├────────────┤ └────┘ ┌──┴─┐ ├────────────┤ ├────────────┤ ├────────────┤ # q_3: |0>─┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ ────── ────────────── ┤CNOT├──────── ┤RX(1.000000)├ ┤RY(1.000000)├ ┤RZ(1.000000)├ # └────────────┘ └────────────┘ └────────────┘ └────┘ └────────────┘ └────────────┘ └────────────┘
BasicEntanglerTemplate¶
- class pyvqnet.qnn.template.BasicEntanglerTemplate(weights=None, num_qubits=1, rotation=pyqpanda.RX)¶
Layers consisting of one-parameter single-qubit rotations on each qubit, followed by a closed chain or ring of CNOT gates.
The ring of CNOT gates connects every qubit with its neighbour, with the last qubit being considered as a neighbour to the first qubit.
The number of layers \(L\) is determined by the first dimension of the argument
weights
.- Parameters:
weights – Weight tensor of shape
(L, len(qubits))
. Each weight is used as a parameter for the rotation, default: None, use random tensor with shape(1,1)
.num_qubits – number of qubits, default: 1.
rotation – one-parameter single-qubit gate to use, default: pyqpanda.RX
Example:
import pyqpanda as pq import numpy as np from pyvqnet.qnn.template import BasicEntanglerTemplate np.random.seed(42) num_qubits = 5 shape = [1, num_qubits] weights = np.random.random(size=shape) machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(num_qubits) circuit = BasicEntanglerTemplate(weights=weights, num_qubits=num_qubits, rotation=pq.RZ) result = circuit.create_circuit(qubits) circuit.print_circuit(qubits) prob = machine.prob_run_dict(result, qubits[0], -1) prob = list(prob.values()) print(prob) # ┌────────────┐ ┌────┐ # q_0: |0>─┤RZ(0.374540)├ ───■── ────── ────── ────── ┤CNOT├ # ├────────────┤ ┌──┴─┐ └──┬─┘ # q_1: |0>─┤RZ(0.950714)├ ┤CNOT├ ───■── ────── ────── ───┼── # ├────────────┤ └────┘ ┌──┴─┐ │ # q_2: |0>─┤RZ(0.731994)├ ────── ┤CNOT├ ───■── ────── ───┼── # ├────────────┤ └────┘ ┌──┴─┐ │ # q_3: |0>─┤RZ(0.598658)├ ────── ────── ┤CNOT├ ───■── ───┼── # ├────────────┤ └────┘ ┌──┴─┐ │ # q_4: |0>─┤RZ(0.156019)├ ────── ────── ────── ┤CNOT├ ───■── # └────────────┘ └────┘ # [1.0, 0.0]
StronglyEntanglingTemplate¶
- class pyvqnet.qnn.template.StronglyEntanglingTemplate(weights=None, num_qubits=1, ranges=None)¶
Layers consisting of single qubit rotations and entanglers, inspired by the circuit-centric classifier design .
The argument
weights
contains the weights for each layer. The number of layers \(L\) is therefore derived from the first dimension ofweights
.The 2-qubit CNOT gate, act on the \(M\) number of qubits, \(i = 1,...,M\). The second qubit of each gate is given by \((i+r)\mod M\), where \(r\) is a hyperparameter called the range, and \(0 < r < M\).
- Parameters:
weights – weight tensor of shape
(L, M, 3)
, default: None, use random tensor with shape(1,1,3)
.num_qubits – number of qubits, default: 1.
ranges – sequence determining the range hyperparameter for each subsequent layer; default: None, using \(r=l \mod M\) for the \(l\) th layer and \(M\) qubits.
Example:
import pyqpanda as pq import numpy as np from pyvqnet.qnn.template import StronglyEntanglingTemplate np.random.seed(42) num_qubits = 3 shape = [2, num_qubits, 3] weights = np.random.random(size=shape) machine = pq.CPUQVM() # outside machine.init_qvm() # outside qubits = machine.qAlloc_many(num_qubits) circuit = StronglyEntanglingTemplate(weights, num_qubits=num_qubits) result = circuit.create_circuit(qubits) circuit.print_circuit(qubits) prob = machine.prob_run_dict(result, qubits[0], -1) prob = list(prob.values()) print(prob) # ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────┐ ┌────────────┐ > # q_0: |0>─┤RZ(0.374540)├ ┤RY(0.950714)├ ┤RZ(0.731994)├ ───■── ────── ┤CNOT├──────────── ┤RZ(0.708073)├ > # ├────────────┤ ├────────────┤ ├────────────┤ ┌──┴─┐ └──┬┬┴───────────┐ ├────────────┤ > # q_1: |0>─┤RZ(0.598658)├ ┤RY(0.156019)├ ┤RZ(0.155995)├ ┤CNOT├ ───■── ───┼┤RZ(0.832443)├ ┤RY(0.212339)├ > # ├────────────┤ ├────────────┤ ├────────────┤ └────┘ ┌──┴─┐ │└────────────┘ ├────────────┤ > # q_2: |0>─┤RZ(0.058084)├ ┤RY(0.866176)├ ┤RZ(0.601115)├ ────── ┤CNOT├ ───■────────────── ┤RZ(0.183405)├ > # └────────────┘ └────────────┘ └────────────┘ └────┘ └────────────┘ > # # ┌────────────┐ ┌────────────┐ ┌────┐ # q_0: |0>┤RY(0.020584)├ ┤RZ(0.969910)├ ───■── ┤CNOT├ ────── # ├────────────┤ └────────────┘ │ └──┬─┘ ┌────┐ # q_1: |0>┤RZ(0.181825)├ ────────────── ───┼── ───■── ┤CNOT├ # ├────────────┤ ┌────────────┐ ┌──┴─┐ └──┬─┘ # q_2: |0>┤RY(0.304242)├ ┤RZ(0.524756)├ ┤CNOT├ ────── ───■── # └────────────┘ └────────────┘ └────┘ #[0.6881335561525671, 0.31186644384743273]
ComplexEntangelingTemplate¶
- class pyvqnet.qnn.ComplexEntangelingTemplate(weights, num_qubits, depth)¶
A strongly entangled layer consisting of U3 gates and CNOT gates. This circuit template is from the following paper: https://arxiv.org/abs/1804.00633.
- Parameters:
weights – parameter, shape of [depth,num_qubits,3]
num_qubits – Number of qubits.
depth – The depth of the subcircuit.
Example:
from pyvqnet.qnn import ComplexEntangelingTemplate import pyqpanda as pq from pyvqnet. tensor import * depth=3 num_qubits = 8 shape = [depth, num_qubits, 3] weights = tensor.randn(shape) machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(num_qubits) circuit = ComplexEntangelingTemplate(weights, num_qubits=num_qubits,depth=depth) result = circuit. create_circuit(qubits) circuit. print_circuit(qubits) # q_0: |0>─┤U3(1.115555,-0.025096,1.326895)├── ───■── ────── ───────────────────────────────── ────────────────────────────────── > # ├───────────────────────────────┴─┐ ┌──┴─┐ ┌───────────────────────────────┐ > # q_1: |0>─┤U3(-0.884622,-0.239700,-0.701955)├ ┤CNOT├ ───■── ┤U3(0.811768,0.537290,-0.433107)├ ────────────────────────────────── > # ├────────────────────────────────┬┘ └────┘ ┌──┴─┐ └───────────────────────────────┘ ┌────────────────────────────────┐ > # q_2: |0>─┤U3(-0.387148,-0.322480,0.238582)├─ ────── ┤CNOT├ ───■───────────────────────────── ┤U3(-0.188015,-1.828407,0.070222)├ > # ├────────────────────────────────┤ └────┘ ┌──┴─┐ └────────────────────────────────┘ > # q_3: |0>─┤U3(-0.679633,1.638090,-1.341497)├─ ────── ────── ┤CNOT├─────────────────────────── ───■────────────────────────────── > # ├──────────────────────────────┬─┘ └────┘ ┌──┴─┐ > # q_4: |0>─┤U3(2.073888,1.251795,0.238305)├─── ────── ────── ───────────────────────────────── ┤CNOT├──────────────────────────── > # ├──────────────────────────────┤ └────┘ > # q_5: |0>─┤U3(0.247473,2.772012,1.864166)├─── ────── ────── ───────────────────────────────── ────────────────────────────────── > # ├──────────────────────────────┴─┐ > # q_6: |0>─┤U3(-1.421337,-0.866551,0.739282)├─ ────── ────── ───────────────────────────────── ────────────────────────────────── > # ├────────────────────────────────┤ > # q_7: |0>─┤U3(-3.707045,0.690364,-0.979904)├─ ────── ────── ───────────────────────────────── ────────────────────────────────── > # └────────────────────────────────┘ > # > # q_0: |0>────────────────────────────────── ────────────────────────────────── ──────────────────────────────── > # > # q_1: |0>────────────────────────────────── ────────────────────────────────── ──────────────────────────────── > # > # q_2: |0>────────────────────────────────── ────────────────────────────────── ──────────────────────────────── > # ┌────────────────────────────────┐ > # q_3: |0>┤U3(0.516395,-0.823623,-0.804430)├ ────────────────────────────────── ──────────────────────────────── > # └────────────────────────────────┘ ┌────────────────────────────────┐ > # q_4: |0>───■────────────────────────────── ┤U3(-1.420068,1.063462,-0.107385)├ ──────────────────────────────── > # ┌──┴─┐ └────────────────────────────────┘ ┌──────────────────────────────┐ > # q_5: |0>┤CNOT├──────────────────────────── ───■────────────────────────────── ┤U3(0.377809,0.204278,0.386830)├ > # └────┘ ┌──┴─┐ └──────────────────────────────┘ > # q_6: |0>────────────────────────────────── ┤CNOT├──────────────────────────── ───■──────────────────────────── > # └────┘ ┌──┴─┐ > # q_7: |0>────────────────────────────────── ────────────────────────────────── ┤CNOT├────────────────────────── > # └────┘ > # ┌────┐ ┌────────────────────────────────┐ > # q_0: |0>┤CNOT├──────────────────────────────── ┤U3(-0.460444,-1.150054,0.318044)├ ───■── ────── ────────────────────────────────── > # └──┬─┘ └────────────────────────────────┘ ┌──┴─┐ ┌────────────────────────────────┐ > # q_1: |0>───┼────────────────────────────────── ────────────────────────────────── ┤CNOT├ ───■── ┤U3(-1.255487,0.589956,-0.378491)├ > # │ └────┘ ┌──┴─┐ └────────────────────────────────┘ > # q_2: |0>───┼────────────────────────────────── ────────────────────────────────── ────── ┤CNOT├ ───■────────────────────────────── > # │ └────┘ ┌──┴─┐ > # q_3: |0>───┼────────────────────────────────── ────────────────────────────────── ────── ────── ┤CNOT├──────────────────────────── > # │ └────┘ > # q_4: |0>───┼────────────────────────────────── ────────────────────────────────── ────── ────── ────────────────────────────────── > # │ > # q_5: |0>───┼────────────────────────────────── ────────────────────────────────── ────── ────── ────────────────────────────────── > # │┌────────────────────────────────┐ > # q_6: |0>───┼┤U3(-0.760777,-0.867848,0.016680)├ ────────────────────────────────── ────── ────── ────────────────────────────────── > # │└────────────────────────────────┘ ┌────────────────────────────────┐ > # q_7: |0>───■────────────────────────────────── ┤U3(-1.462434,-0.173843,1.211081)├ ────── ────── ────────────────────────────────── > # └────────────────────────────────┘ > # > # q_0: |0>───────────────────────────────── ───────────────────────────────── ──────────────────────────────── > # > # q_1: |0>───────────────────────────────── ───────────────────────────────── ──────────────────────────────── > # ┌───────────────────────────────┐ > # q_2: |0>┤U3(0.558638,0.218889,-0.241834)├ ───────────────────────────────── ──────────────────────────────── > # └───────────────────────────────┘ ┌───────────────────────────────┐ > # q_3: |0>───■───────────────────────────── ┤U3(0.740361,-0.336978,0.171089)├ ──────────────────────────────── > # ┌──┴─┐ └───────────────────────────────┘ ┌──────────────────────────────┐ > # q_4: |0>┤CNOT├─────────────────────────── ───■───────────────────────────── ┤U3(0.585393,0.204842,0.682543)├ > # └────┘ ┌──┴─┐ └──────────────────────────────┘ > # q_5: |0>───────────────────────────────── ┤CNOT├─────────────────────────── ───■──────────────────────────── > # └────┘ ┌──┴─┐ > # q_6: |0>───────────────────────────────── ───────────────────────────────── ┤CNOT├────────────────────────── > # └────┘ > # q_7: |0>───────────────────────────────── ───────────────────────────────── ──────────────────────────────── > # > # ┌────┐ ┌───────────────────────────────┐ > # q_0: |0>─────────────────────────────────── ┤CNOT├────────────────────────────── ┤U3(0.657827,1.434924,-0.328996)├ > # └──┬─┘ └───────────────────────────────┘ > # q_1: |0>─────────────────────────────────── ───┼──────────────────────────────── ───────────────────────────────── > # │ > # q_2: |0>─────────────────────────────────── ───┼──────────────────────────────── ───────────────────────────────── > # │ > # q_3: |0>─────────────────────────────────── ───┼──────────────────────────────── ───────────────────────────────── > # │ > # q_4: |0>─────────────────────────────────── ───┼──────────────────────────────── ───────────────────────────────── > # ┌─────────────────────────────────┐ │ > # q_5: |0>┤U3(-2.134247,-0.783461,-0.200094)├ ───┼──────────────────────────────── ───────────────────────────────── > # └─────────────────────────────────┘ │┌──────────────────────────────┐ > # q_6: |0>───■─────────────────────────────── ───┼┤U3(1.816030,0.572931,1.683584)├ ───────────────────────────────── > # ┌──┴─┐ │└──────────────────────────────┘ ┌───────────────────────────────┐ > # q_7: |0>┤CNOT├───────────────────────────── ───■──────────────────────────────── ┤U3(0.661537,0.214565,-0.325014)├ > # └────┘ └───────────────────────────────┘ > # ┌────┐ # q_0: |0>───■── ────── ────── ────── ────── ────── ────── ┤CNOT├ # ┌──┴─┐ └──┬─┘ # q_1: |0>┤CNOT├ ───■── ────── ────── ────── ────── ────── ───┼── # └────┘ ┌──┴─┐ │ # q_2: |0>────── ┤CNOT├ ───■── ────── ────── ────── ────── ───┼── # └────┘ ┌──┴─┐ │ # q_3: |0>────── ────── ┤CNOT├ ───■── ────── ────── ────── ───┼── # └────┘ ┌──┴─┐ │ # q_4: |0>────── ────── ────── ┤CNOT├ ───■── ────── ────── ───┼── # └────┘ ┌──┴─┐ │ # q_5: |0>────── ────── ────── ────── ┤CNOT├ ───■── ────── ───┼── # └────┘ ┌──┴─┐ │ # q_6: |0>────── ────── ────── ────── ────── ┤CNOT├ ───■── ───┼── # └────┘ ┌──┴─┐ │ # q_7: |0>────── ────── ────── ────── ────── ────── ┤CNOT├ ───■──
Quantum_Embedding¶
- class pyvqnet.qnn.Quantum_Embedding(qubits, machine, num_repetitions_input, depth_input, num_unitary_layers, num_repetitions)¶
Use RZ,RY,RZ to create variational quantum circuits that encode classical data into quantum states. See Quantum embeddings for machine learning. After the class is initialized, its member function
compute_circuit
is a running function, which can be input as a parameter. TheQuantumLayerV2
class can utilizecompute_circuit
to build a layer of quantum machine learning model.- Parameters:
qubits – Qubits requested by pyqpanda.
machine – Quantum virtual machine applied by pyqpanda.
num_repetitions_input – Number of repetitions to encode input in the submodule.
depth_input – The feature dimension of the input data.
num_unitary_layers – Number of repetitions of the variational quantum gates in each submodule.
num_repetitions – Number of repetitions for the submodule.
Example:
from pyvqnet.qnn import QuantumLayerV2,Quantum_Embedding from pyvqnet.tensor import tensor import pyqpanda as pq depth_input = 2 num_repetitions = 2 num_repetitions_input = 2 num_unitary_layers = 2 loacl_machine = pq.CPUQVM() loacl_machine.init_qvm() nq = depth_input * num_repetitions_input qubits = loacl_machine.qAlloc_many(nq) cubits = loacl_machine.cAlloc_many(nq) data_in = tensor.ones([12, depth_input]) qe = Quantum_Embedding(qubits, loacl_machine, num_repetitions_input, depth_input, num_unitary_layers, num_repetitions) qlayer = QuantumLayerV2(qe.compute_circuit, qe.param_num) data_in.requires_grad = True y = qlayer.forward(data_in) print(y) # [ # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894], # [0.2302894] # ]
Measure the quantum circuit¶
expval_qcloud¶
- pyvqnet.qnn.measure.expval_qcloud(machine, prog, pauli_str_dict, qlists, clists, shots=1000, qtype=pq.real_chip_type.origin_72)¶
Expectation value of the supplied Hamiltonian observables of QCloud.
if the observables are \(0.7Z\otimes X\otimes I+0.2I\otimes Z\otimes I\), then
Hamiltonian
dict
would be{{'Z0, X1':0.7} ,{'Z1':0.2}}
.- Parameters:
machine – machine created by qpanda
prog – quantum program created by qpanda
pauli_str_dict – Hamiltonian observables
qlists – qubit allocated by pyQPanda
clists – cbit allocated by pyQPanda
shots – measure times, default:1000.
qtype – Set the type of qmachine measurement, the default is “” indicating non-qcloud. Set pq.real_chip_type.origin_72 for real chips.
- Returns:
expectation
Example:
from pyqpanda import * input = [0.56, 0.1] m_machine = QCloud() m_machine.init_qvm("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx") m_prog = pq.QProg() m_qlist = m_machine.qAlloc_many(4) m_clist = m_machine.cAlloc_many(4) cir = pq.QCircuit() cir.insert(pq.RZ(m_qlist[0],input[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[1])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[3])) cir.insert(pq.RY(m_qlist[1],input[1])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[2])) m_prog.insert(cir) pauli_dict = {'Z0 X1':10,'Y2':-0.543} from pyvqnet.qnn import expval_qcloud exp2 = expval_qcloud(m_machine,m_prog,pauli_dict,m_qlist,m_clist,shots=100) print(exp2)
expval¶
- pyvqnet.qnn.measure.expval(machine, prog, pauli_str_dict, qubits)¶
Expectation value of the supplied Hamiltonian observables
if the observables are \(0.7Z\otimes X\otimes I+0.2I\otimes Z\otimes I\), then
Hamiltonian
dict
would be{{'Z0, X1':0.7} ,{'Z1':0.2}}
.expval api only supports on QPanda CPUQVM now.Please checks https://pyqpanda-toturial.readthedocs.io/zh/latest/index.html for alternative api.
- Parameters:
machine – machine created by qpanda
prog – quantum program created by qpanda
pauli_str_dict – Hamiltonian observables
qubits – qubit allocated by pyQPanda
- Returns:
expectation
Example:
import pyqpanda as pq from pyvqnet.qnn.measure import expval input = [0.56, 0.1] m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_prog = pq.QProg() m_qlist = m_machine.qAlloc_many(3) cir = pq.QCircuit() cir.insert(pq.RZ(m_qlist[0],input[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[1])) cir.insert(pq.RY(m_qlist[1],input[1])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[2])) m_prog.insert(cir) pauli_dict = {'Z0 X1':10,'Y2':-0.543} exp2 = expval(m_machine,m_prog,pauli_dict,m_qlist) print(exp2) pq.destroy_quantum_machine(m_machine) #0.9983341664682731
QuantumMeasure¶
- pyvqnet.qnn.measure.QuantumMeasure(measure_qubits: list, prog, machine, qubits, shots: int = 1000, qtype='')¶
Calculates circuits quantum measurement. Return the normalized result of the measurements obtained by the Monte Carlo method.
Please checks https://pyqpanda-toturial.readthedocs.io/zh/latest/Measure.html?highlight=measure_all for alternative api.
QuantumMeasure api only supports on QPanda
CPUQVM
orQCloud
now.- Parameters:
measure_qubits – list contains measure qubits index.
prog – quantum program from qpanda
machine – quantum virtual machine allocated by pyQPanda
qubits – qubit allocated by pyQPanda
shots – measure time,default 1000
qtype – Set the type of qmachine measurement, the default is “” indicating non-qcloud. Set pq.real_chip_type.origin_72 for real chips.
- Returns:
returns the normalized result of the measurements obtained by the Monte Carlo method.
Example:
from pyvqnet.qnn.measure import QuantumMeasure import pyqpanda as pq input = [0.56,0.1] measure_qubits = [0,2] m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_prog = pq.QProg() m_qlist = m_machine.qAlloc_many(3) cir = pq.QCircuit() cir.insert(pq.RZ(m_qlist[0],input[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[1])) cir.insert(pq.RY(m_qlist[1],input[1])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[2])) cir.insert(pq.H(m_qlist[0])) cir.insert(pq.H(m_qlist[1])) cir.insert(pq.H(m_qlist[2])) m_prog.insert(cir) rlt_quant = QuantumMeasure(measure_qubits,m_prog,m_machine,m_qlist) print(rlt_quant) #[0.25, 0.264, 0.257, 0.229]
ProbsMeasure¶
- pyvqnet.qnn.measure.ProbsMeasure(measure_qubits: list, prog, machine, qubits)¶
Calculates circuits probabilities measurement.
Please checks https://pyqpanda-toturial.readthedocs.io/zh/latest/PMeasure.html for alternative api.
ProbsMeasure api only supports on QPanda
CPUQVM
orQCloud
now.- Parameters:
measure_qubits – list contains measure qubits index.
prog – quantum program from qpanda
qubits – qubit allocated by pyQPanda
- Returns:
prob of measure qubits in lexicographic order.
Example:
from pyvqnet.qnn.measure import ProbsMeasure import pyqpanda as pq input = [0.56,0.1] measure_qubits = [0,2] m_machine = pq.init_quantum_machine(pq.QMachineType.CPU) m_prog = pq.QProg() m_qlist = m_machine.qAlloc_many(3) cir = pq.QCircuit() cir.insert(pq.RZ(m_qlist[0],input[0])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[1])) cir.insert(pq.RY(m_qlist[1],input[1])) cir.insert(pq.CNOT(m_qlist[0],m_qlist[2])) cir.insert(pq.H(m_qlist[0])) cir.insert(pq.H(m_qlist[1])) cir.insert(pq.H(m_qlist[2])) m_prog.insert(cir) rlt_prob = ProbsMeasure([0,2],m_prog,m_machine,m_qlist) print(rlt_prob) #[0.2499999999999947, 0.2499999999999947, 0.2499999999999947, 0.2499999999999947]
DensityMatrixFromQstate¶
- pyvqnet.qnn.measure.DensityMatrixFromQstate(state, indices)¶
Calculate the density matrix of quantum state vector in the computational basis.
- Parameters:
state – one-dimensional list state vector. The size of this list should be
(2**N,)
for some integer valueN
. qstate should start from 000 -> 111.indices – list of qubit indices in the considered subsystem.
- Returns:
A density matrix of size “(2**len(indices), 2**len(indices))”.
Example:
from pyvqnet.qnn.measure import DensityMatrixFromQstate qstate = [(0.9306699299765968+0j), (0.18865613455240968+0j), (0.1886561345524097+0j), (0.03824249173404786+0j), -0.048171819846746615j, -0.00976491131165138j, -0.23763904794287155j, -0.048171819846746615j] print(DensityMatrixFromQstate(qstate,[0,1])) # [[0.86846704+0.j 0.1870241 +0.j 0.17604699+0.j 0.03791166+0.j] # [0.1870241 +0.j 0.09206345+0.j 0.03791166+0.j 0.01866219+0.j] # [0.17604699+0.j 0.03791166+0.j 0.03568649+0.j 0.00768507+0.j] # [0.03791166+0.j 0.01866219+0.j 0.00768507+0.j 0.00378301+0.j]]
VN_Entropy¶
- pyvqnet.qnn.measure.VN_Entropy(state, indices, base=None)¶
Computes Von Neumann entropy from a state vector on a given list of qubits.
\[S( \rho ) = -\text{Tr}( \rho \log ( \rho ))\]- Parameters:
state – one-dimensional list state vector. The size of this list should be
(2**N,)
for some integer valueN
. qstate should start from 000 ->111.indices – list of qubit indices in the considered subsystem.
base – the base of the logarithm. If None, the natural logarithm is used. Default: None.
- Returns:
floating point value for the von Neumann entropy.
Example:
from pyvqnet.qnn.measure import VN_Entropy qstate = [(0.9022961387408862 + 0j), -0.06676534788028633j, (0.18290448232350312 + 0j), -0.3293638014158896j, (0.03707657410649268 + 0j), -0.06676534788028635j, (0.18290448232350312 + 0j), -0.013534006039561714j] print(VN_Entropy(qstate, [0, 1])) #0.14592917648464448
Mutal_Info¶
- pyvqnet.qnn.measure.Mutal_Info(state, indices0, indices1, base=None)¶
Calculates the mutual information of the state vectors on the given two lists of sub-qubits.
\[I(A, B) = S(\rho^A) + S(\rho^B) - S(\rho^{AB})\]where \(S\) is the von Neumann entropy.
Mutual information is a measure of the correlation between two subsystems. More specifically, it quantifies the amount of information one system gains by measuring another.
Each state can be given as a state vector in the computation base.
- Parameters:
state – one-dimensional list state vector. The size of this list should be
(2**N,)
for some integer valueN
.qstate should start from 000 ->111indices0 – list of qubit indices in the first subsystem.
indices1 – a list of qubit indices in the second subsystem.
base – the base of the logarithm. If None, the natural logarithm is used. Default: None.
- Returns:
Mutual information between subsystems
Example:
from pyvqnet.qnn.measure import Mutal_Info qstate = [(0.9022961387408862 + 0j), -0.06676534788028633j, (0.18290448232350312 + 0j), -0.3293638014158896j, (0.03707657410649268 + 0j), -0.06676534788028635j, (0.18290448232350312 + 0j), -0.013534006039561714j] print(Mutal_Info(qstate, [0], [2], 2)) #0.13763425302805887
MeasurePauliSum¶
- pyvqnet.qnn.measure.MeasurePauliSum(machine, prog, obs_list, qlists)¶
Expectation value of the supplied Hamiltonian observables.
- Parameters:
machine – machine created by qpanda.
prog – quantum program created by qpanda.
pauli_str_dict – Hamiltonian observables.
qlists – qubit allocated by pyQpanda.qAlloc_many().
- Returns:
expectation
Example:
from pyvqnet.qnn.measure import MeasurePauliSum import pyqpanda as pq x = [0.56, 0.1] obs_list = [{'wires': [0, 2, 3], 'observables': ['X', 'Y', 'Z'], 'coefficient': [1, 0.5, 0.4]}, {'wires': [0, 1, 2], 'observables': ['X', 'Y', 'Z'], 'coefficient': [1, 0.5, 0.4]}] m_machine = pq.CPUQVM() m_machine.init_qvm() m_prog = pq.QProg() m_qlist = m_machine.qAlloc_many(4) cir = pq.QCircuit() cir.insert(pq.RZ(m_qlist[0], x[0])) cir.insert(pq.RZ(m_qlist[1], x[0])) cir.insert(pq.CNOT(m_qlist[0], m_qlist[1])) cir.insert(pq.RY(m_qlist[2], x[1])) cir.insert(pq.CNOT(m_qlist[0], m_qlist[2])) cir.insert(pq.RZ(m_qlist[3], x[1])) m_prog.insert(cir) result = MeasurePauliSum(m_machine, m_prog, obs_list, m_qlist) print(result) m_machine.finalize() # [0.40000000000000013, 0.3980016661112104]
VarMeasure¶
- pyvqnet.qnn.measure.VarMeasure(machine, prog, actual_qlist)¶
Variance of the supplied observable.
- Parameters:
machine – machine created by qpanda.
prog – quantum program created by qpanda.
actual_qlist – qubit allocated by pyQpanda.qAlloc_many().
- Returns:
var
Example:
import pyqpanda as pq from pyvqnet.qnn.measure import VarMeasure cir = pq.QCircuit() machine = pq.CPUQVM() # outside machine.init_qvm() # outside qubits = machine.qAlloc_many(2) cir.insert(pq.RX(qubits[0], 0.5)) cir.insert(pq.H(qubits[1])) cir.insert(pq.CNOT(qubits[0], qubits[1])) prog1 = pq.QProg() prog1.insert(cir) var_result = VarMeasure(machine, prog1, qubits[0]) print(var_result) # 0.2298488470659339
Purity¶
- pyvqnet.qnn.measure.Purity(state, qubits_idx)¶
Calculate the purity on a particular qubit from the state vector.
\[\gamma = \text{Tr}(\rho^2)\]where \(\rho\) is a density matrix. The purity of a normalized quantum state satisfies \(\frac{1}{d} \leq \gamma \leq 1\) , where \(d\) is the dimension of the Hilbert space. The purity of the pure state is 1.
- Parameters:
state – Quantum state obtained from pyqpanda get_qstate()
qubits_idx – index of qubits whose purity is to be calculated
- Returns:
purity
Examples:
from pyvqnet.qnn import Purity qstate = [(0.9306699299765968 + 0j), (0.18865613455240968 + 0j), (0.1886561345524097 + 0j), (0.03824249173404786 + 0j), -0.048171819846746615j, -0.00976491131165138j, -0.23763904794287155j, -0.048171819846746615j] pp = Purity(qstate, [1]) print(pp) #0.902503479761881
Quantum Machine Learning Algorithm Interface¶
Quantum Generative Adversarial Networks for learning and loading random distributions¶
Quantum Generative Adversarial Networks(QGAN )algorithm uses pure quantum variational circuits to prepare the generated quantum states with specific random distribution, which can reduce the logic gates required to generate specific quantum states and reduce the complexity of quantum circuits.It uses the classical GAN model structure, which has two sub-models: Generator and Discriminator. The Generator generates a specific distribution for the quantum circuit.And the Discriminator discriminates the generated data samples generated by the Generator and the real randomly distributed training data samples. Here is an example of VQNet implementing QGAN learning and loading random distributions based on the paper Quantum Generative Adversarial Networks for learning and loading random distributions of Christa Zoufal.
In order to realize the construction of QGANAPI
class of quantum generative adversarial network by VQNet, the quantum generator is used to prepare the initial state of the real distributed data. The number of quantum bits is 3, and the repetition times of the internal parametric circuit module of the quantum generator is 1. Meanwhile, KL is used as the metric for the QGAN loading random distribution.
import pickle
import os
import pyqpanda as pq
from pyvqnet.qnn.qgan.qgan_utils import QGANAPI
import numpy as np
num_of_qubits = 3 # paper config
rep = 1
number_of_data = 10000
# Load data samples from different distributions
mu = 1
sigma = 1
real_data = np.random.lognormal(mean=mu, sigma=sigma, size=number_of_data)
# intial
save_dir = None
qgan_model = QGANAPI(
real_data,
# numpy generated data distribution, 1 - dim.
num_of_qubits,
batch_size=2000,
num_epochs=2000,
q_g_cir=None,
bounds = [0.0,2**num_of_qubits -1],
reps=rep,
metric="kl",
tol_rel_ent=0.01,
if_save_param_dir=save_dir
)
The following is the train
module of QGAN.
# train
qgan_model.train() # train qgan
The eval
module of QGAN is designed to draw the loss function curve and probability distribution diagram between the random distribution prepared by QGAN and the real distribution.
# show probability distribution function of generated distribution and real distribution
qgan_model.eval(real_data) #draw pdf
The get_trained_quantum_parameters
module of QGAN is used to get training parameters and output them as a numpy array. If save_DIR
is not empty, the training parameters are saved to a file.The Load_param_and_eval
module of QGAN loads training parameters, and the get_circuits_with_trained_param
module obtains pyQPanda circuit generated by quantum generator after training.
# get trained quantum parameters
param = qgan_model.get_trained_quantum_parameters()
print(f" trained param {param}")
#load saved parameters files
if save_dir is not None:
path = os.path.join(
save_dir, qgan_model._start_time + "trained_qgan_param.pickle")
with open(path, "rb") as file:
t3 = pickle.load(file)
param = t3["quantum_parameters"]
print(f" trained param {param}")
#show probability distribution function of generated distribution and real distribution
qgan_model.load_param_and_eval(param)
#calculate metric
print(qgan_model.eval_metric(param, "kl"))
#get generator quantum circuit
m_machine = pq.CPUQVM()
m_machine.init_qvm()
qubits = m_machine.qAlloc_many(num_of_qubits)
qpanda_cir = qgan_model.get_circuits_with_trained_param(qubits)
print(qpanda_cir)
In general, QGAN learning and loading random distribution requires multiple training models with different random seeds to obtain the expected results. For example, the following is the graph of the probability distribution function between the lognormal distribution implemented by QGAN and the real lognormal distribution, and the loss function curve between QGAN’s generator and discriminator.
quantum kernal SVM¶
In machine learning tasks, data often cannot be separated by a hyperplane in the original space. A common technique for finding such hyperplanes is to apply a nonlinear transformation function to the data. This function is called a feature map, through which we can calculate how close the data points are in this new feature space for the classification task of machine learning.
This example refers to the thesis: Supervised learning with quantum enhanced feature spaces . The first method constructs variational circuits for data classification tasks.
gen_vqc_qsvm_data
is the data needed to generate this example. vqc_qsvm
is a variable sub-circuit class used to classify the input data.
The vqc_qsvm.plot()
function visualizes the distribution of the data.
""" VQC QSVM """ from pyvqnet.qnn.svm import vqc_qsvm, gen_vqc_qsvm_data import matplotlib.pyplot as plt import numpy as np batch_size = 40 maxiter = 40 training_size = 20 test_size = 10 gap = 0.3 #sub-circuits repeat times rep = 3 #defines QSVM class VQC_QSVM = vqc_qsvm(batch_size, maxiter, rep) #randomly generates data from thesis. train_features, test_features, train_labels, test_labels, samples = \ gen_vqc_qsvm_data(training_size=training_size, test_size=test_size, gap=gap) VQC_QSVM.plot(train_features, test_features, train_labels, test_labels, samples) #train VQC_QSVM.train(train_features, train_labels) #test rlt, acc_1 = VQC_QSVM.predict(test_features, test_labels) print(f"testing_accuracy {acc_1}")
In addition to the above-mentioned direct use of variational quantum circuits to map classical data features to quantum feature spaces, in the paper Supervised learning with quantum enhanced feature spaces, the method of directly estimating kernel functions using quantum circuits and classifying them using classical support vector machines is also introduced. Analogy to various kernel functions in classical SVM \(K(i,j)\) , use quantum kernel function to define the inner product of classical data in quantum feature space \(\phi(\mathbf{x}_i)\) :
Using VQNet and pyQPanda, we define a QuantumKernel_VQNet
to generate a quantum kernel function and use sklearn
for classification:
import numpy as np
import pyqpanda as pq
from sklearn.svm import SVC
from pyqpanda import *
from pyqpanda.Visualization.circuit_draw import *
from pyvqnet.qnn.svm import QuantumKernel_VQNet, gen_vqc_qsvm_data
import matplotlib
try:
matplotlib.use('TkAgg')
except:
pass
import matplotlib.pyplot as plt
train_features, test_features,train_labels, test_labels, samples = gen_vqc_qsvm_data(20,5,0.3)
quantum_kernel = QuantumKernel_VQNet(n_qbits=2)
quantum_svc = SVC(kernel=quantum_kernel.evaluate)
quantum_svc.fit(train_features, train_labels)
score = quantum_svc.score(test_features, test_labels)
print(f"quantum kernel classification test score: {score}")
Simultaneous Perturbation Stochastic Approximation optimizers¶
- pyvqnet.qnn.SPSA(maxiter: int = 1000, save_steps: int = 1, last_avg: int = 1, c0: float = _C0, c1: float = 0.2, c2: float = 0.602, c3: float = 0.101, c4: float = 0, init_para=None, model=None, calibrate_flag=False)¶
Simultaneous Perturbation Stochastic Approximation (SPSA) optimizer.
SPSA provides a stochastic method for approximating the gradient of a multivariate differentiable cost function. To achieve this, the cost function is evaluated twice using a perturbed parameter vector: each component of the original parameter vector is simultaneously shifted by a randomly generated value. Further information is available on the SPSA website.
- Parameters:
maxiter – The maximum number of iterations to perform. Default value: 1000.
save_steps – Save the intermediate information of each save_steps step. Default value: 1.
last_avg – Averaging parameter for last_avg iterations. If last_avg = 1, only the last iteration is considered. Default value: 1.
c0 – initial a. Step size for updating parameters. Default value: 0.2*pi
c1 – initial c. The step size used to approximate the gradient. Default: 0.1.
c2 – alpha from the paper, used to adjust a(c0) at each iteration. Default value: 0.602.
c3 – gamma in the paper, used to adjust c(c1) at each iteration. Default value: 0.101.
c4 – Also used to control the parameters of a. Default value: 0.
init_para – Initialization parameters. Default: None.
model – Parametric model: model. Default: None.
calibrate_flag – whether to calibrate hpyer parameters a and c, default value: False.
- Returns:
an SPSA optimizer instance
Warning
SPSA only supports 1-dim paramters.
Example:
import numpy as np import pyqpanda as pq import sys sys.path.insert(0, "../") import pyvqnet from pyvqnet.nn.module import Module from pyvqnet.qnn import SPSA from pyvqnet.tensor.tensor import QTensor from pyvqnet.qnn import AngleEmbeddingCircuit, expval, QuantumLayerV2, expval from pyvqnet.qnn.template import BasicEntanglerTemplate class Model_spsa(Module): def __init__(self): super(Model_spsa, self).__init__() self.qvc = QuantumLayerV2(layer_fn_spsa_pq, 3) def forward(self, x): y = self.qvc(x) return y def layer_fn_spsa_pq(input, weights): num_of_qubits = 1 machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(num_of_qubits) c1 = AngleEmbeddingCircuit(input, qubits) weights =weights.reshape([4,1]) bc_class = BasicEntanglerTemplate(weights, 1) c2 = bc_class.create_circuit(qubits) m_prog = pq.QProg() m_prog.insert(c1) m_prog.insert(c2) pauli_dict = {'Z0': 1} exp2 = expval(machine, m_prog, pauli_dict, qubits) return exp2 model = Model_spsa() optimizer = SPSA(maxiter=20, init_para=model.parameters(), model=model, )
- pyvqnet.qnn.SPSA._step(input_data)¶
use SPSA to optimize input data.
- Parameters:
input_data – input data
- Returns:
train_para: final parameter
theta_best: The average parameters of after last last_avg.
Example:
import numpy as np import pyqpanda as pq import sys sys.path.insert(0, "../") import pyvqnet from pyvqnet.nn.module import Module from pyvqnet.qnn import SPSA from pyvqnet.tensor.tensor import QTensor from pyvqnet.qnn import AngleEmbeddingCircuit, expval, QuantumLayerV2, expval from pyvqnet.qnn.template import BasicEntanglerTemplate class Model_spsa(Module): def __init__(self): super(Model_spsa, self).__init__() self.qvc = QuantumLayerV2(layer_fn_spsa_pq, 3) def forward(self, x): y = self.qvc(x) return y def layer_fn_spsa_pq(input, weights): num_of_qubits = 1 machine = pq.CPUQVM() machine.init_qvm() qubits = machine.qAlloc_many(num_of_qubits) c1 = AngleEmbeddingCircuit(input, qubits) weights =weights.reshape([4,1]) bc_class = BasicEntanglerTemplate(weights, 1) c2 = bc_class.create_circuit(qubits) m_prog = pq.QProg() m_prog.insert(c1) m_prog.insert(c2) pauli_dict = {'Z0': 1} exp2 = expval(machine, m_prog, pauli_dict, qubits) return exp2 model = Model_spsa() optimizer = SPSA(maxiter=20, init_para=model.parameters(), model=model, ) data = QTensor(np.array([[0.27507603]])) p = model.parameters() p[0].data = pyvqnet._core.Tensor( np.array([3.97507603, 3.12950603, 1.00854038, 1.25907603])) optimizer._step(input_data=data) y = model(data) print(y)
Automatic differential simulation of variational quantum circuits¶
VQNet is based on the construction of automatic differential operators and some commonly used quantum logic gates, quantum circuits and measurement methods. Automatic differentiation can be used to calculate gradients instead of the quantum circuit parameter-shift method. We can use VQC operators to form complex neural networks like other Modules. The virtual machine QMachine needs to be defined in Module, and the states in the machine need to be reset_states based on the input batchsize. Please see the following example for details:
Example:
from pyvqnet.nn import Module,Linear,ModuleList from pyvqnet.qnn.vqc.qcircuit import VQC_HardwareEfficientAnsatz,RZZ,RZ from pyvqnet.qnn.vqc import Probability,QMachine from pyvqnet import tensor class QM(Module): def __init__(self, name=""): super().__init__(name) self.linearx = Linear(4,2) self.ansatz = VQC_HardwareEfficientAnsatz(4, ["rx", "RY", "rz"], entangle_gate="cnot", entangle_rules="linear", depth=2) #VQC based RZ on 0 bits self.encode1 = RZ(wires=0) #VQC based RZ on 1 bit self.encode2 = RZ(wires=1) #VQC-based probability measurement on 0, 2 bits self.measure = Probability(wires=[0,2]) #Quantum device QMachine, uses 4 bits. self.device = QMachine(4) def forward(self, x, *args, **kwargs): #States must be reset to the same batchsize as the input. self.device.reset_states(x.shape[0]) y = self.linearx(x) #Encode the input to the RZ gate. Note that the input must be of shape [batchsize,1] self.encode1(params = y[:, [0]],q_machine = self.device,) #Encode the input to the RZ gate. Note that the input must be of shape [batchsize,1] self.encode2(params = y[:, [1]],q_machine = self.device,) self.ansatz(q_machine =self.device) return self.measure(q_machine =self.device) bz=3 inputx = tensor.arange(1.0,bz*4+1).reshape([bz,4]) inputx.requires_grad= True #Define like other Modules qlayer = QM() #Prequel y = qlayer(inputx) #reversepass y.backward() print(y)
Simulator,Quantum Gates and Measure¶
QMachine¶
- class pyvqnet.qnn.vqc.QMachine(num_wires, dtype=pyvqnet.kcomplex64)¶
A simulator class for variable quantum computing, including statevectors whose states attribute is a quantum circuit.
- Parameters:
num_wires – number of qubits。
dtype – the data type of the calculated data, the default is pyvqnet.kcomplex64, and the corresponding parameter precision is pyvqnet.kfloat32
- Returns:
Output QMachine。
Example:
from pyvqnet.qnn.vqc import QMachine qm = QMachine(4) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
i¶
- pyvqnet.qnn.vqc.i(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine I。
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import i,QMachine qm = QMachine(4) i(q_machine=qm, wires=1) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
I¶
- class pyvqnet.qnn.vqc.I(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an I logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import I,QMachine device = QMachine(4) layer = I(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
hadamard¶
- pyvqnet.qnn.vqc.hadamard(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine hadamard.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import hadamard,QMachine qm = QMachine(4) hadamard(q_machine=qm, wires=1) print(qm.states) # [[[[[0.7071068+0.j 0. +0.j] # [0. +0.j 0. +0.j]] # # [[0.7071068+0.j 0. +0.j] # [0. +0.j 0. +0.j]]] # # # [[[0. +0.j 0. +0.j] # [0. +0.j 0. +0.j]] # # [[0. +0.j 0. +0.j] # [0. +0.j 0. +0.j]]]]]
Hadamard¶
- class pyvqnet.qnn.vqc.Hadamard(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a Hadamard logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import Hadamard,QMachine device = QMachine(4) layer = Hadamard(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
t¶
- pyvqnet.qnn.vqc.t(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine t.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import t,QMachine qm = QMachine(4) t(q_machine=qm, wires=1) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
T¶
- class pyvqnet.qnn.vqc.T(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a T logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import T,QMachine device = QMachine(4) layer = T(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
s¶
- pyvqnet.qnn.vqc.s(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine s.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import s,QMachine qm = QMachine(4) s(q_machine=qm, wires=1) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
S¶
- class pyvqnet.qnn.vqc.S(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an S logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import S,QMachine device = QMachine(4) layer = S(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
paulix¶
- pyvqnet.qnn.vqc.paulix(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine paulix.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import paulix,QMachine qm = QMachine(4) paulix(q_machine=qm, wires=1) print(qm.states) # [[[[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
PauliX¶
- class pyvqnet.qnn.vqc.PauliX(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a PauliX logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import PauliX,QMachine device = QMachine(4) layer = PauliX(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
pauliy¶
- pyvqnet.qnn.vqc.pauliy(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine pauliy.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import pauliy,QMachine qm = QMachine(4) pauliy(q_machine=qm, wires=1) print(qm.states) # [[[[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+1.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
PauliY¶
- class pyvqnet.qnn.vqc.PauliY(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a PauliY logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import PauliY,QMachine device = QMachine(4) layer = PauliY(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
pauliz¶
- pyvqnet.qnn.vqc.pauliz(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine pauliz.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import pauliz,QMachine qm = QMachine(4) pauliz(q_machine=qm, wires=1) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
PauliZ¶
- class pyvqnet.qnn.vqc.PauliZ(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a PauliZ logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import PauliZ,QMachine device = QMachine(4) layer = PauliZ(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
x1¶
- pyvqnet.qnn.vqc.x1(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine x1.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import x1,QMachine qm = QMachine(4) x1(q_machine=qm, wires=1) print(qm.states) # [[[[[0.7071068+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. -0.7071068j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
X1¶
- class pyvqnet.qnn.vqc.X1(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an X1 logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import X1,QMachine device = QMachine(4) layer = X1(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
y1¶
- pyvqnet.qnn.vqc.y1(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine y1.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import y1,QMachine qm = QMachine(4) y1(q_machine=qm, wires=1) print(qm.states) # [[[[[0.7071068+0.j 0. +0.j] # [0. +0.j 0. +0.j]] # # [[0.7071068+0.j 0. +0.j] # [0. +0.j 0. +0.j]]] # # # [[[0. +0.j 0. +0.j] # [0. +0.j 0. +0.j]] # # [[0. +0.j 0. +0.j] # [0. +0.j 0. +0.j]]]]]
Y1¶
- class pyvqnet.qnn.vqc.Y1(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an Y1 logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import Y1,QMachine device = QMachine(4) layer = Y1(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
z1¶
- pyvqnet.qnn.vqc.z1(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine z1.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import z1,QMachine qm = QMachine(4) z1(q_machine=qm, wires=1) print(qm.states) # [[[[[0.7071068-0.7071068j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
Z1¶
- class pyvqnet.qnn.vqc.Z1(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an Z1 logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import Z1,QMachine device = QMachine(4) layer = Z1(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
rx¶
- pyvqnet.qnn.vqc.rx(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine rx.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import rx,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) rx(q_machine=qm, wires=1,params=QTensor([0.5])) print(qm.states) # [[[[[0.9689124+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. -0.247404j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
RX¶
- class pyvqnet.qnn.vqc.RX(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an RX logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import RX,QMachine device = QMachine(4) layer = RX(has_params= True, trainable= True, wires=0) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
ry¶
- pyvqnet.qnn.vqc.ry(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine ry.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import ry,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) ry(q_machine=qm, wires=1,params=QTensor([0.5])) print(qm.states) # [[[[[0.9689124+0.j 0. +0.j] # [0. +0.j 0. +0.j]] # # [[0.247404 +0.j 0. +0.j] # [0. +0.j 0. +0.j]]] # # # [[[0. +0.j 0. +0.j] # [0. +0.j 0. +0.j]] # # [[0. +0.j 0. +0.j] # [0. +0.j 0. +0.j]]]]]
RY¶
- class pyvqnet.qnn.vqc.RY(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an RY logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import RY,QMachine device = QMachine(4) layer = RY(has_params= True, trainable= True, wires=0) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
rz¶
- pyvqnet.qnn.vqc.rz(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine rz.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import rz,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) rz(q_machine=qm, wires=1,params=QTensor([0.5])) print(qm.states) # [[[[[0.9689124-0.247404j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
RZ¶
- class pyvqnet.qnn.vqc.RZ(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an RZ logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import RZ,QMachine device = QMachine(4) layer = RZ(has_params= True, trainable= True, wires=0) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
crx¶
- pyvqnet.qnn.vqc.crx(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine crx.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.crx(q_machine=qm,wires=[0,2], params=QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
CRX¶
- class pyvqnet.qnn.vqc.CRX(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a CRX logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CRX,QMachine device = QMachine(4) layer = CRX(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
cry¶
- pyvqnet.qnn.vqc.cry(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine cry.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.cry(q_machine=qm,wires=[0,2], params=QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
CRY¶
- class pyvqnet.qnn.vqc.CRY(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a CRY logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CRY,QMachine device = QMachine(4) layer = CRY(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
crz¶
- pyvqnet.qnn.vqc.crz(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine crz.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.crz(q_machine=qm,wires=[0,2], params=QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
CRZ¶
- class pyvqnet.qnn.vqc.CRZ(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a CRZ logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CRZ,QMachine device = QMachine(4) layer = CRZ(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
p¶
- pyvqnet.qnn.vqc.p(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine p.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import p,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) p(q_machine=qm, wires=[1,0],params=QTensor([24.0])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
u1¶
- pyvqnet.qnn.vqc.u1(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine u1.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import u1,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) u1(q_machine=qm, wires=1,params=QTensor([24.0])) print(qm.states) # [[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
U1¶
- class pyvqnet.qnn.vqc.U1(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a U1 logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import U1,QMachine device = QMachine(4) layer = U1(has_params= True, trainable= True, wires=0) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
u2¶
- pyvqnet.qnn.vqc.u2(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine u2.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import u2,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) u2(q_machine=qm, wires=1,params=QTensor([[24.0,-3]])) print(qm.states) # [[[[[0.7071068+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0.2999398-0.6403406j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
U2¶
- class pyvqnet.qnn.vqc.U2(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a U2 logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import U2,QMachine device = QMachine(4) layer = U2(has_params= True, trainable= True, wires=0) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
u3¶
- pyvqnet.qnn.vqc.u3(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine u3.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import u3,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) u3(q_machine=qm, wires=1,params=QTensor([[24.0,-3,1]])) print(qm.states) # [[[[[0.843854 +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0.5312032+0.0757212j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
U3¶
- class pyvqnet.qnn.vqc.U3(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a U3 logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import U3,QMachine device = QMachine(4) layer = U3(has_params= True, trainable= True, wires=0) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
cy¶
- pyvqnet.qnn.vqc.cy(q_machine, wires, params=None, use_dagger=False)¶
Apply quantum logic gate cy to the state vector in q_machine.
- Parameters:
q_machine – Quantum virtual machine device.
wires – Qubit index.
params – Parameter matrix, default is None.
use_dagger – Whether to use conjugate transpose, the default is False.
Example:
from pyvqnet.qnn.vqc import cy,QMachine qm = QMachine(4) cy(q_machine=qm,wires=(1,0)) print(qm.states) # [[[[[1.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]], # [[[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]]]]
CY¶
- class pyvqnet.qnn.vqc.CY(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a CY logic category.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it comes with parameters to be trained. If this layer uses external input data to construct a logic gate matrix, set it to False. If the parameters to be trained need to be initialized from this layer, it will be True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CY,QMachine device = QMachine(4) layer = CY(wires=[0,1]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
cnot¶
- pyvqnet.qnn.vqc.cnot(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine cnot.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import cnot,QMachine qm = QMachine(4) cnot(q_machine=qm,wires=[1,0]) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
CNOT¶
- class pyvqnet.qnn.vqc.CNOT(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a CNOT logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CNOT,QMachine device = QMachine(4) layer = CNOT(wires=[0,1]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
cr¶
- pyvqnet.qnn.vqc.cr(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine cr.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import cr,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) cr(q_machine=qm,wires=[1,0],params=QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
CR¶
- class pyvqnet.qnn.vqc.CR(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a CR logic gate.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CR,QMachine device = QMachine(4) layer = CR(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
iswap¶
- pyvqnet.qnn.vqc.iswap(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine iswap.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import iswap,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) iswap(q_machine=qm,wires=[1,0],params=QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
swap¶
- pyvqnet.qnn.vqc.swap(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine swap.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import swap,QMachine qm = QMachine(4) swap(q_machine=qm,wires=[1,0]) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
SWAP¶
- class pyvqnet.qnn.vqc.SWAP(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a SWAP logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import SWAP,QMachine device = QMachine(4) layer = SWAP(wires=[0,1]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
cswap¶
- pyvqnet.qnn.vqc.cswap(q_machine, wires, params=None, use_dagger=False)¶
Apply the quantum logic gate cswap to the state vector in q_machine.
- Parameters:
q_machine – Quantum virtual machine device.
wires – Qubit index.
params – Parameter matrix, default is None.
use_dagger – Whether to use conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import cswap,QMachine qm = QMachine(4) cswap(q_machine=qm,wires=[1,0,3],) print(qm.states) # [[[[[1.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]], # [[[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]]]]
CSWAP ————————————————– ————-
- class pyvqnet.qnn.vqc.CSWAP(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a SWAP logic gate class.
\[\begin{split}CSWAP = \begin{bmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \end{bmatrix}.\end{split}\]- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it comes with parameters to be trained. If this layer uses external input data to construct a logic gate matrix, set it to False. If the parameters to be trained need to be initialized from this layer, it will be True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64, or pyvqnet.kcomplex128, corresponding to float input or double input parameters respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CSWAP,QMachine device = QMachine(4) layer = CSWAP(wires=[0,1,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states) # [[[[[1.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]], # [[[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]]], # [[[[1.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]], # [[[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]], # [[0.+0.j,0.+0.j], # [0.+0.j,0.+0.j]]]]]
cz¶
- pyvqnet.qnn.vqc.cz(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine cz.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import cz,QMachine qm = QMachine(4) cz(q_machine=qm,wires=[1,0]) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
CZ¶
- class pyvqnet.qnn.vqc.CZ(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a CZ logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import CZ,QMachine device = QMachine(4) layer = CZ(wires=[0,1]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
rxx¶
- pyvqnet.qnn.vqc.rxx(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine rxx.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import rxx,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) rxx(q_machine=qm,wires=[1,0],params=QTensor([0.2])) print(qm.states) # [[[[[0.9950042+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. -0.0998334j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
RXX¶
- class pyvqnet.qnn.vqc.RXX(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an RXX logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import RXX,QMachine device = QMachine(4) layer = RXX(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
ryy¶
- pyvqnet.qnn.vqc.ryy(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine ryy.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import ryy,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) ryy(q_machine=qm,wires=[1,0],params=QTensor([0.2])) print(qm.states) # [[[[[0.9950042+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.0998334j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
RYY¶
- class pyvqnet.qnn.vqc.RYY(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an RYY logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import RYY,QMachine device = QMachine(4) layer = RYY(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
rzz¶
- pyvqnet.qnn.vqc.rzz(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine rzz.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import rzz,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) rzz(q_machine=qm,wires=[1,0],params=QTensor([0.2])) print(qm.states) # [[[[[0.9950042-0.0998334j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
RZZ¶
- class pyvqnet.qnn.vqc.RZZ(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an RZZ logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import RZZ,QMachine device = QMachine(4) layer = RZZ(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
rzx¶
- pyvqnet.qnn.vqc.rzx(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine rzx.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import rzx,QMachine from pyvqnet.tensor import QTensor qm = QMachine(4) rzx(q_machine=qm,wires=[1,0],params=QTensor([0.2])) print(qm.states) # [[[[[0.9950042+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. -0.0998334j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
RZX¶
- class pyvqnet.qnn.vqc.RZX(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an RZX logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import RZX,QMachine device = QMachine(4) layer = RZX(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
toffoli¶
- pyvqnet.qnn.vqc.toffoli(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine toffoli.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import toffoli,QMachine qm = QMachine(4) toffoli(q_machine=qm,wires=[0,1,2]) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
Toffoli¶
- class pyvqnet.qnn.vqc.Toffoli(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a Toffoli logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import Toffoli,QMachine device = QMachine(4) layer = Toffoli( wires=[0,2,1]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
isingxx¶
- pyvqnet.qnn.vqc.isingxx(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine isingxx.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.isingxx(q_machine=qm,wires=[0,1], params = QTensor([0.5])) print(qm.states) # [[[[[0.9689124+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. -0.247404j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
IsingXX¶
- class pyvqnet.qnn.vqc.IsingXX(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an IsingXX logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import IsingXX,QMachine device = QMachine(4) layer = IsingXX(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
isingyy¶
- pyvqnet.qnn.vqc.isingyy(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine isingyy.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.isingyy(q_machine=qm,wires=[0,1], params = QTensor([0.5])) print(qm.states) # [[[[[0.9689124+0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.247404j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
IsingYY¶
- class pyvqnet.qnn.vqc.IsingYY(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an IsingYY logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import IsingYY,QMachine device = QMachine(4) layer = IsingYY(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
isingzz¶
- pyvqnet.qnn.vqc.isingzz(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine isingzz.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.isingzz(q_machine=qm,wires=[0,1], params = QTensor([0.5])) print(qm.states) # [[[[[0.9689124-0.247404j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
IsingZZ¶
- class pyvqnet.qnn.vqc.IsingZZ(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an IsingZZ logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import IsingZZ,QMachine device = QMachine(4) layer = IsingZZ(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
isingxy¶
- pyvqnet.qnn.vqc.isingxy(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine isingxy.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.isingxy(q_machine=qm,wires=[0,1], params = QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
IsingXY¶
- class pyvqnet.qnn.vqc.IsingXY(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an IsingXY logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import IsingXY,QMachine device = QMachine(4) layer = IsingXY(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
phaseshift¶
- pyvqnet.qnn.vqc.phaseshift(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine phaseshift.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.phaseshift(q_machine=qm,wires=[0], params = QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
PhaseShift¶
- class pyvqnet.qnn.vqc.PhaseShift(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a PhaseShift logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import PhaseShift,QMachine device = QMachine(4) layer = PhaseShift(has_params= True, trainable= True, wires=1) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
multirz¶
- pyvqnet.qnn.vqc.multirz(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine multirz.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.multirz(q_machine=qm,wires=[0, 1], params = QTensor([0.5])) print(qm.states) # [[[[[0.9689124-0.247404j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]] # # # [[[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]] # # [[0. +0.j 0. +0.j ] # [0. +0.j 0. +0.j ]]]]]
MultiRZ¶
- class pyvqnet.qnn.vqc.MultiRZ(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a MultiRZ logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import MultiRZ,QMachine device = QMachine(4) layer = MultiRZ(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
sdg¶
- pyvqnet.qnn.vqc.sdg(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine sdg.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.sdg(q_machine=qm,wires=[0]) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
SDG¶
- class pyvqnet.qnn.vqc.SDG(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define an SDG logic category.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import SDG,QMachine device = QMachine(4) layer = SDG(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
tdg¶
- pyvqnet.qnn.vqc.tdg(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine tdg.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.tdg(q_machine=qm,wires=[0]) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
TDG¶
- class pyvqnet.qnn.vqc.TDG(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a TDG logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import TDG,QMachine device = QMachine(4) layer = TDG(wires=0) batchsize=1 device.reset_states(1) layer(q_machine = device) print(device.states)
controlledphaseshift¶
- pyvqnet.qnn.vqc.controlledphaseshift(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine controlledphaseshift.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) for i in range(4): vqc.hadamard(q_machine=qm, wires=i) vqc.controlledphaseshift(q_machine=qm,params=QTensor([0.5]),wires=[0,1]) print(qm.states) # [[[[[0.25 +0.j 0.25 +0.j ] # [0.25 +0.j 0.25 +0.j ]] # # [[0.25 +0.j 0.25 +0.j ] # [0.25 +0.j 0.25 +0.j ]]] # # # [[[0.25 +0.j 0.25 +0.j ] # [0.25 +0.j 0.25 +0.j ]] # # [[0.2193956+0.1198564j 0.2193956+0.1198564j] # [0.2193956+0.1198564j 0.2193956+0.1198564j]]]]]
ControlledPhaseShift¶
- class pyvqnet.qnn.vqc.ControlledPhaseShift(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a ControlledPhaseShift logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import ControlledPhaseShift,QMachine device = QMachine(4) layer = ControlledPhaseShift(has_params= True, trainable= True, wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
multicnot¶
- pyvqnet.qnn.vqc.multicnot(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine multicnot.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.multicnot(q_machine=qm, wires=[0, 1]) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
MultiCnot¶
- class pyvqnet.qnn.vqc.MultiCnot(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a MultiCnot logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import MultiCnot,QMachine device = QMachine(4) layer = MultiCnot(wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
multixcnot¶
- pyvqnet.qnn.vqc.multixcnot(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine multixcnot.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.multixcnot(q_machine=qm, wires=[0, 1]) print(qm.states) # [[[[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
MultiXcnot¶
- class pyvqnet.qnn.vqc.MultiXcnot(has_params: bool = False, trainable: bool = False, init_params=None, wires=None, dtype=pyvqnet.kcomplex64, use_dagger=False)¶
Define a MultiXcnot logic gate class.
- Parameters:
has_params – Whether there are parameters, such as RX, RY and other gates need to be set to True, those without parameters need to be set to False, the default is False.
trainable – Whether it contains parameters to be trained. If the layer uses external input data to construct a logic gate matrix, set it to False. If it contains parameters to be trained, it is True. The default is False.
init_params – Initialization parameters, used to encode classic data QTensor, default is None.
wires – Bit index of wire action, default is None.
dtype – The data precision of the internal matrix of the logic gate can be set to pyvqnet.kcomplex64 or pyvqnet.kcomplex128, corresponding to float input or double input parameter respectively.
use_dagger – Whether to use the transposed conjugate version of this gate, the default is False.
- Returns:
A Module that can be used to train the model.
Example:
from pyvqnet.qnn.vqc import MultiXcnot,QMachine device = QMachine(4) layer = MultiXcnot(wires=[0,2]) batchsize = 2 device.reset_states(batchsize) layer(q_machine = device) print(device.states)
single_excitation¶
- pyvqnet.qnn.vqc.single_excitation(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine single_excitation.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) vqc.single_excitation(q_machine=qm, wires=[0, 1],num_wires=4, params=QTensor([0.5])) print(qm.states) # [[[[[1.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]] # # # [[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]]]]]
double_excitation¶
- pyvqnet.qnn.vqc.double_excitation(q_machine, wires, params=None, use_dagger=False)¶
Acting quantum logic gates on state vectors in q_machine double_excitation.
- Parameters:
q_machine – quantum virtual machine device.
wires – qubit idx.
params – parameter matrix, defaults to None.
use_dagger – whether to conjugate transpose, the default is False.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import QMachine import pyvqnet.qnn.vqc as vqc from pyvqnet.tensor import QTensor qm = QMachine(4) for i in range(4): vqc.hadamard(q_machine=qm, wires=i) vqc.isingzz(q_machine=qm, params=QTensor([0.55]), wires=[1,0]) vqc.double_excitation(q_machine=qm, params=QTensor([0.55]), wires=[0,1,2,3]) print(qm.states) # [[[[[0.2406063-0.0678867j 0.2406063-0.0678867j] # [0.2406063-0.0678867j 0.1662296-0.0469015j]] # # [[0.2406063+0.0678867j 0.2406063+0.0678867j] # [0.2406063+0.0678867j 0.2406063+0.0678867j]]] # # # [[[0.2406063+0.0678867j 0.2406063+0.0678867j] # [0.2406063+0.0678867j 0.2406063+0.0678867j]] # # [[0.2969014-0.0837703j 0.2406063-0.0678867j] # [0.2406063-0.0678867j 0.2406063-0.0678867j]]]]]
VQC_BasisEmbedding¶
- pyvqnet.qnn.vqc.VQC_BasisEmbedding(basis_state, q_machine)¶
Encode n binary features into the ground state of n qubits.
For example, for
basis_state=([0, 1, 1])
, the ground state of the quantum system is \(|011 \rangle\).- Parameters:
basis_state – binary input of size
(n)
.q_machine – quantum virtual machine device。
- Returns:
output QTensor。
Example:
from pyvqnet.qnn.vqc import VQC_BasisEmbedding,QMachine qm = QMachine(3) VQC_BasisEmbedding(basis_state=[1,1,0],q_machine=qm) print(qm.states) # [[[[0.+0.j 0.+0.j] # [0.+0.j 0.+0.j]] # # [[0.+0.j 0.+0.j] # [1.+0.j 0.+0.j]]]]
VQC_AngleEmbedding¶
- pyvqnet.qnn.vqc.VQC_AngleEmbedding(input_feat, wires, q_machine: QMachine, rotation: str = 'X')¶
Encodes the \(N\) feature into the rotation angle of the \(n\) qubit, where \(N \leq n\).
Rotation can be selected as: ‘X’ , ‘Y’ , ‘Z’, such as the parameter definition of
rotation
is:rotation='X'
Use feature as angle for RX rotation.rotation='Y'
Use feature as angle for RY rotation.rotation='Z'
Use feature as angle for RZ rotation.
wires
denote the idx of rotation gates on the qubits.- Parameters:
input_feat – array representing the parameters.
wires – qubit idx.
q_machine – Quantum virtual machine device.
rotation – Rotation gate,default is “X”.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import VQC_AngleEmbedding, QMachine from pyvqnet.tensor import QTensor qm = QMachine(2) VQC_AngleEmbedding(QTensor([2.2, 1]), [0, 1], q_machine=qm, rotation='X') print(qm.states) # [[[ 0.398068 +0.j 0. -0.2174655j] # [ 0. -0.7821081j -0.4272676+0.j ]]] VQC_AngleEmbedding(QTensor([2.2, 1]), [0, 1], q_machine=qm, rotation='Y') print(qm.states) # [[[-0.0240995+0.6589843j 0.4207355+0.2476033j] # [ 0.4042482-0.2184162j 0. -0.3401631j]]] VQC_AngleEmbedding(QTensor([2.2, 1]), [0, 1], q_machine=qm, rotation='Z') print(qm.states) # [[[0.659407 +0.0048471j 0.4870554-0.0332093j] # [0.4569675+0.047989j 0.340018 +0.0099326j]]]
VQC_AmplitudeEmbedding¶
- pyvqnet.qnn.vqc.VQC_AmplitudeEmbeddingCircuit(input_feature, q_machine)¶
Encode a \(2^n\) feature into an amplitude vector of \(n\) qubits.
- Parameters:
input_feature – A numpy array representing the parameters.
q_machine – Quantum virtual machine device.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import VQC_AmplitudeEmbedding, QMachine from pyvqnet.tensor import QTensor qm = QMachine(3) VQC_AmplitudeEmbedding(QTensor([3.2,-2,-2,0.3,12,0.1,2,-1]), q_machine=qm) print(qm.states) # [[[[ 0.2473717+0.j -0.1546073+0.j] # [-0.1546073+0.j 0.0231911+0.j]] # # [[ 0.9276441+0.j 0.0077304+0.j] # [ 0.1546073+0.j -0.0773037+0.j]]]]
VQC_IQPEmbedding¶
- pyvqnet.qnn.vqc.VQC_IQPEmbedding(input_feat, q_machine: QMachine, rep: int = 1)¶
Diagonal gates using IQP lines encode \(n\) features into \(n\) qubits.
The encoding was proposed by Havlicek et al. (2018).
By specifying
rep
, basic IQP lines can be repeated.- Parameters:
input_feat – A numpy array representing the parameters.
q_machine – Quantum virtual machine device.
rep – The number of times to repeat the quantum circuit block, the default number is 1.
- Returns:
Output QTensor。
Example:
from pyvqnet.qnn.vqc import VQC_IQPEmbedding, QMachine from pyvqnet.tensor import QTensor qm = QMachine(3) VQC_IQPEmbedding(QTensor([3.2,-2,-2]), q_machine=qm) print(qm.states) # [[[[ 0.0309356-0.3521973j 0.3256442+0.1376801j] # [ 0.3256442+0.1376801j 0.2983474+0.1897071j]] # # [[ 0.0309356+0.3521973j -0.3170519-0.1564546j] # [-0.3170519-0.1564546j -0.2310978-0.2675701j]]]]
VQC_RotCircuit¶
- pyvqnet.qnn.vqc.VQC_RotCircuit(q_machine, wire, params)¶
Arbitrary single-qubit rotations.
\[\begin{split}R(\phi,\theta,\omega) = RZ(\omega)RY(\theta)RZ(\phi)= \begin{bmatrix} e^{-i(\phi+\omega)/2}\cos(\theta/2) & -e^{i(\phi-\omega)/2}\sin(\theta/2) \\ e^{-i(\phi-\omega)/2}\sin(\theta/2) & e^{i(\phi+\omega)/2}\cos(\theta/2) \end{bmatrix}.\end{split}\]- Parameters:
q_machine – Quantum virtual machine device.
wire – Qubit idx。
params – Parameters \([\phi, \theta, \omega]\).
- Returns:
Output QTensor.
Example:
from pyvqnet.qnn.vqc import VQC_RotCircuit, QMachine from pyvqnet.tensor import QTensor qm = QMachine(3) VQC_RotCircuit(q_machine=qm, wire=[1],params=QTensor([2.0,1.5,2.1])) print(qm.states) # [[[[-0.3373617-0.6492732j 0. +0.j ] # [ 0.6807868-0.0340677j 0. +0.j ]] # # [[ 0. +0.j 0. +0.j ] # [ 0. +0.j 0. +0.j ]]]]
VQC_CRotCircuit¶
- pyvqnet.qnn.vqc.VQC_CRotCircuit(para, control_qubits, rot_wire, q_machine)¶
Controlled Rot circuit.
\[\begin{split}CR(\phi, \theta, \omega) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0\\ 0 & 0 & e^{-i(\phi+\omega)/2}\cos(\theta/2) & -e^{i(\phi-\omega)/2}\sin(\theta/2)\\ 0 & 0 & e^{-i(\phi-\omega)/2}\sin(\theta/2) & e^{i(\phi+\omega)/2}\cos(\theta/2) \end{bmatrix}.\end{split}\]- Parameters:
para – numpy array representing the parameters.
control_qubits – Idx of control bits.
rot_wire – Idx of rot bits.
q_machine – Quantum virtual machine device.
- Returns:
Output QTensor.
Example:
from pyvqnet.tensor import QTensor from pyvqnet.qnn.vqc.qcircuit import VQC_CRotCircuit from pyvqnet.qnn.vqc import QMachine, MeasureAll p = QTensor([2, 3, 4.0]) qm = QMachine(2) VQC_CRotCircuit(p, 0, 1, qm) m = MeasureAll(obs={"Z0": 1}) exp = m(q_machine=qm) print(exp) # [[0.9999999]]
VQC_Controlled_Hadamard¶
- pyvqnet.qnn.vqc.VQC_Controlled_Hadamard(wires, q_machine)¶
Controlled Hadamard logic.
\[\begin{split}CH = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ 0 & 0 & \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \end{bmatrix}.\end{split}\]- Parameters:
wires – Qubit idx, the first is the control bit, and the list length is 2.
q_machine – Quantum virtual machine device.
Examples:
from pyvqnet.tensor import QTensor from pyvqnet.qnn.vqc.qcircuit import VQC_Controlled_Hadamard from pyvqnet.qnn.vqc import QMachine, MeasureAll p = QTensor([0.2, 3, 4.0]) qm = QMachine(3) VQC_Controlled_Hadamard([1, 0], qm) m = MeasureAll(obs={"Z0": 1}) exp = m(q_machine=qm) print(exp) # [[1.]]
VQC_CCZ¶
- pyvqnet.qnn.vqc.VQC_CCZ(wires, q_machine)¶
Controlled-controlled-Z logic。
\[\begin{split}CCZ = \begin{pmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0\\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & -1 \end{pmatrix}\end{split}\]- Parameters:
wires – List of qubit subscripts, the first bit is the control bit. The list length is 3.
q_machine – Quantum virtual machine device.
- Returns:
pyqpanda QCircuit
Example:
from pyvqnet.tensor import QTensor from pyvqnet.qnn.vqc.qcircuit import VQC_CCZ from pyvqnet.qnn.vqc import QMachine, MeasureAll p = QTensor([0.2, 3, 4.0]) qm = QMachine(3) VQC_CCZ([1, 0, 2], qm) m = MeasureAll(obs={"Z0": 1}) exp = m(q_machine=qm) print(exp) # [[0.9999999]]
VQC_FermionicSingleExcitation¶
- pyvqnet.qnn.vqc.VQC_FermionicSingleExcitation(weight, wires, q_machine)¶
A coupled cluster single-excitation operator for exponentiating the tensor product of a Pauli matrix. The matrix form is given by:
\[\hat{U}_{pr}(\theta) = \mathrm{exp} \{ \theta_{pr} (\hat{c}_p^\dagger \hat{c}_r -\mathrm{H.c.}) \},\]- Parameters:
weight – The parameter on qubit p has only one element.
wires – Denotes a subset of qubit indices in the interval [r, p]. Minimum length must be 2. The first index value is interpreted as r and the last index value as p. The intermediate index is acted on by the CNOT gate to calculate the parity of the qubit set.
q_machine – Quantum virtual machine device.
- Returns:
pyqpanda QCircuit
Examples:
from pyvqnet.tensor import QTensor from pyvqnet.qnn.vqc.qcircuit import VQC_FermionicSingleExcitation from pyvqnet.qnn.vqc import QMachine, MeasureAll qm = QMachine(3) p0 = QTensor([0.5]) VQC_FermionicSingleExcitation(p0, [1, 0, 2], qm) m = MeasureAll(obs={"Z0": 1}) exp = m(q_machine=qm) print(exp) # [[0.9999998]]
VQC_FermionicDoubleExcitation¶
- pyvqnet.qnn.vqc.VQC_FermionicDoubleExcitation(weight, wires1, wires2, q_machine)¶
The coupled clustering dual excitation operator that exponentiates the tensor product of the Pauli matrix, the matrix form is given by:
\[\hat{U}_{pqrs}(\theta) = \mathrm{exp} \{ \theta (\hat{c}_p^\dagger \hat{c}_q^\dagger \hat{c}_r \hat{c}_s - \mathrm{H.c.}) \},\]where \(\hat{c}\) and \(\hat{c}^\dagger\) are the fermion annihilation and Create operators and indices \(r, s\) and \(p, q\) in the occupied and are empty molecular orbitals, respectively. Use the Jordan-Wigner transformation The fermion operator defined above can be written as According to the Pauli matrix (for more details, see arXiv:1805.04340)
\[\begin{split}\hat{U}_{pqrs}(\theta) = \mathrm{exp} \Big\{ \frac{i\theta}{8} \bigotimes_{b=s+1}^{r-1} \hat{Z}_b \bigotimes_{a=q+1}^{p-1} \hat{Z}_a (\hat{X}_s \hat{X}_r \hat{Y}_q \hat{X}_p + \hat{Y}_s \hat{X}_r \hat{Y}_q \hat{Y}_p +\\ \hat{X}_s \hat{Y}_r \hat{Y}_q \hat{Y}_p + \hat{X}_s \hat{X}_r \hat{X}_q \hat{Y}_p - \mathrm{H.c.} ) \Big\}\end{split}\]- Parameters:
weight – Variable parameter.
wires1 – The index list of qubits representing the subset of qubits occupied in the interval [s, r]. The first index is interpreted as s, the last as r. CNOT gates operate on intermediate indices to compute the parity of a set of qubits.
wires2 – The index list of qubits representing the subset of qubits occupied in the interval [q, p]. The first index is interpreted as q, the last as p. CNOT gates operate on intermediate indices to compute the parity of a set of qubits.
q_machine – Quantum virtual machine device.
- Returns:
pyqpanda QCircuit
Examples:
from pyvqnet.tensor import QTensor from pyvqnet.qnn.vqc.qcircuit import VQC_FermionicDoubleExcitation from pyvqnet.qnn.vqc import QMachine, MeasureAll qm = QMachine(5) p0 = QTensor([0.5]) VQC_FermionicDoubleExcitation(p0, [0, 1], [2, 3], qm) m = MeasureAll(obs={"Z0": 1}) exp = m(q_machine=qm) print(exp) # [[0.9999998]]
VQC_UCCSD¶
- pyvqnet.qnn.vqc.VQC_UCCSD(weights, wires, s_wires, d_wires, init_state, q_machine)¶
Realize the unitary coupled cluster single-excitation and double-excitation design (UCCSD). UCCSD is the proposed VQE design, commonly used to run quantum chemistry simulations.
Within the first-order Trotter approximation, the UCCSD unitary function is given by:
\[\hat{U}(\vec{\theta}) = \prod_{p > r} \mathrm{exp} \Big\{\theta_{pr} (\hat{c}_p^\dagger \hat{c}_r-\mathrm{H.c.}) \Big\} \prod_{p > q > r > s} \mathrm{exp} \Big\{\theta_{pqrs} (\hat{c}_p^\dagger \hat{c}_q^\dagger \hat{c}_r \hat{c}_s-\mathrm{H.c.}) \Big\}\]where \(\hat{c}\) and \(\hat{c}^\dagger\) are the fermion annihilation and Create operators and indices \(r, s\) and \(p, q\) in the occupied and are empty molecular orbitals, respectively. (For more details see arXiv:1805.04340):
- Parameters:
weights – A
(len(s_wires)+ len(d_wires))
tensor containing the parameters \(\theta_{pr}\) and \(\theta_{pqrs}\) input Z rotationFermionicSingleExcitation
andFermionicDoubleExcitation
.wires – Qubit indexing of template effects
s_wires – A sequence of lists
[r,...,p]
containing qubit indices produced by a single excitation \(\vert r, p \rangle = \hat{c}_p^\dagger \hat{c}_r \vert \mathrm{HF} \rangle\), where \(\vert \mathrm{HF} \rangle\) represents the Hartree-Fock reference state.d_wires – sequence of lists, each list containing two lists specify indices
[s, ...,r]
and[q,...,p]
Define double excitation: math:vert s, r, q, p rangle = hat{c}_p^dagger hat{c}_q^dagger hat{c}_rhat{c}_s vert mathrm{HF} rangle.init_state – length
len(wires)
occupation-number vector representation high frequency state.init_state
is the qubit initialization state.q_machine – Quantum virtual machine device.
Examples:
from pyvqnet.qnn.vqc import VQC_UCCSD, QMachine, MeasureAll from pyvqnet.tensor import QTensor p0 = QTensor([2, 0.5, -0.2, 0.3, -2, 1, 3, 0]) s_wires = [[0, 1, 2], [0, 1, 2, 3, 4], [1, 2, 3], [1, 2, 3, 4, 5]] d_wires = [[[0, 1], [2, 3]], [[0, 1], [2, 3, 4, 5]], [[0, 1], [3, 4]], [[0, 1], [4, 5]]] qm = QMachine(6) VQC_UCCSD(p0, range(6), s_wires, d_wires, QTensor([1.0, 1, 0, 0, 0, 0]), qm) m = MeasureAll(obs={"Z1": 1}) exp = m(q_machine=qm) print(exp) # [[0.963802]]
VQC_ZFeatureMap¶
- pyvqnet.qnn.vqc.VQC_ZFeatureMap(input_feat, q_machine: QMachine, data_map_func=None, rep: int = 2)¶
First-order bubblegum Z-evolution circuit.
For 3 quantum bits and 2 repetitions, the circuit is represented as:
┌───┐┌──────────────┐┌───┐┌──────────────┐ ┤ H ├┤ U1(2.0*x[0]) ├┤ H ├┤ U1(2.0*x[0]) ├ ├───┤├──────────────┤├───┤├──────────────┤ ┤ H ├┤ U1(2.0*x[1]) ├┤ H ├┤ U1(2.0*x[1]) ├ ├───┤├──────────────┤├───┤├──────────────┤ ┤ H ├┤ U1(2.0*x[2]) ├┤ H ├┤ U1(2.0*x[2]) ├ └───┘└──────────────┘└───┘└──────────────┘
The Pauli string is fixed to
Z
. Thus, the first order expansion will be a circuit without entanglement gates.- Parameters:
input_feat – An array representing the input parameters.
q_machine – Quantum machine.
data_map_func – Parameter mapping matrix, design as
data_map = lambda x: x
.rep – Number of module repetitions.
Example:
from pyvqnet.qnn.vqc import VQC_ZFeatureMap, QMachine, hadamard from pyvqnet.tensor import QTensor qm = QMachine(3) for i in range(3): hadamard(q_machine=qm, wires=[i]) VQC_ZFeatureMap(input_feat=QTensor([[0.1,0.2,0.3]]),q_machine = qm) print(qm.states) # [[[[0.3535534+0.j 0.2918002+0.1996312j] # [0.3256442+0.1376801j 0.1910257+0.2975049j]] # # [[0.3465058+0.0702402j 0.246323 +0.2536236j] # [0.2918002+0.1996312j 0.1281128+0.3295255j]]]]
VQC_ZZFeatureMap¶
- pyvqnet.qnn.vqc.VQC_ZZFeatureMap(input_feat, q_machine: QMachine, data_map_func=None, entanglement: Union[str, List[List[int]], Callable[[int], List[int]]] = 'full', rep: int = 2)¶
Second-order Pauli-Z evolution circuits.
For 3 quantum bits, 1 repetition and linear entanglement, the circuit is represented as:
┌───┐┌─────────────────┐ ┤ H ├┤ U1(2.0*φ(x[0])) ├──■────────────────────────────■──────────────────────────────────── ├───┤├─────────────────┤┌─┴─┐┌──────────────────────┐┌─┴─┐ ┤ H ├┤ U1(2.0*φ(x[1])) ├┤ X ├┤ U1(2.0*φ(x[0],x[1])) ├┤ X ├──■────────────────────────────■── ├───┤├─────────────────┤└───┘└──────────────────────┘└───┘┌─┴─┐┌──────────────────────┐┌─┴─┐ ┤ H ├┤ U1(2.0*φ(x[2])) ├──────────────────────────────────┤ X ├┤ U1(2.0*φ(x[1],x[2])) ├┤ X ├ └───┘└─────────────────┘ └───┘└──────────────────────┘└───┘
where
φ
is the classical nonlinear function that defaults toφ(x) = x
if andφ(x,y) = (pi - x)(pi - y)
, design as:def data_map_func(x): coeff = x if x.shape[-1] == 1 else ft.reduce(lambda x, y: (np.pi - x) * (np.pi - y), x) return coeff
- Parameters:
input_feat – An array representing the input parameters.
q_machine – Quantum machine.
data_map_func – Parameter mapping matrix.
entanglement – specified entanglement structure.
rep – Number of module repetitions.
Example:
from pyvqnet.qnn.vqc import VQC_ZZFeatureMap, QMachine from pyvqnet.tensor import QTensor qm = QMachine(3) VQC_ZZFeatureMap(q_machine=qm, input_feat=QTensor([[0.1,0.2,0.3]])) print(qm.states) # [[[[-0.4234843-0.0480578j -0.144067 +0.1220178j] # [-0.0800646+0.0484439j -0.5512857-0.2947832j]] # # [[ 0.0084012-0.0050071j -0.2593993-0.2717131j] # [-0.1961917-0.3470543j 0.2786197+0.0732045j]]]]
VQC_AllSinglesDoubles¶
- pyvqnet.qnn.vqc.VQC_AllSinglesDoubles(weights, q_machine: QMachine, hf_state, wires, singles=None, doubles=None)¶
In this case, we have four single and double excitations to preserve the total spin projection of the Hartree-Fock state.
single_exitation
gate \(G\) acts on quantum bits[0, 2], [0, 4], [1, 3], [1, 5]
, anddouble_exitation
gate anddouble_exitation
operations \(G^{(2)}\) applies to quantum bits[0, 1, 2, 3] , [0, 1, 2, 5], [0, 1, 2, 4], [0, 1, 4, 5]
.The resulting you preserves the number of particles and prepares the n-quantum bit system in a superposition of the initial Hartree-Fock state and the other states encoding the multiple excitation configuration.
- Parameters:
weights – QTensor of size
(len(singles) + len(doubles),)
containing angles that enter vqc.qCircuit.single_excitation and vqc.qCircuit.double_excitation operations sequentiallyq_machine – Quantum machine.
hf_state – Represents the length of the Hartree-Fock state
len(wires)
Occupancy count vector,hf_state
is used to initialize the wires.wires – Qubits action on.
singles – Sequence of lists with the two quantum bit indices on which the single_exitation operation acts.
doubles – Sequence of lists with the two quantum bit indices on which the double_exitation operation acts.
For example, the quantum circuit for the case of two electrons and six quantum bits is shown below:
Example:
from pyvqnet.qnn.vqc import VQC_AllSinglesDoubles, QMachine from pyvqnet.tensor import QTensor qubits = 4 qm = QMachine(qubits) VQC_AllSinglesDoubles(q_machine=qm, weights=QTensor([0.55, 0.11, 0.53]), hf_state = QTensor([1,1,0,0]), singles=[[0, 2], [1, 3]], doubles=[[0, 1, 2, 3]], wires=[0,1,2,3]) print(qm.states) # [ 0. +0.j 0. +0.j 0. +0.j -0.23728043+0.j # 0. +0.j 0. +0.j -0.27552837+0.j 0. +0.j # 0. +0.j -0.12207296+0.j 0. +0.j 0. +0.j # 0.9235152 +0.j 0. +0.j 0. +0.j 0. +0.j]
VQC_BasisRotation¶
- pyvqnet.qnn.vqc.VQC_BasisRotation(q_machine: QMachine, wires, unitary_matrix: QTensor, check=False)¶
Implement a circuit that provides a whole that can be used to perform precise monolithic base rotations.
VQC_BasisRotation
Performs the following you-transform determined by single-particle fermions given in arXiv:1711.04789\(U(u)\)\[U(u) = \exp{\left( \sum_{pq} \left[\log u \right]_{pq} (a_p^\dagger a_q - a_q^\dagger a_p) \right)}.\]\(U(u)\) by using the scheme given in the paper Optica, 3, 1460 (2016). The decomposition of the input You matrix is efficiently implemented by a series of
phaseshift
andsingle_exitation
gates.- Parameters:
q_machine – Quantum machine.
wires – Qubits action on.
unitary_matrix – Specify the matrix of the base transformation.
check – Tests if unitary_matrix is a You matrix.
Example:
from pyvqnet.qnn.vqc import VQC_BasisRotation, QMachine, hadamard, isingzz from pyvqnet.tensor import QTensor import numpy as np V = np.array([[0.73678+0.27511j, -0.5095 +0.10704j, -0.06847+0.32515j], [0.73678+0.27511j, -0.5095 +0.10704j, -0.06847+0.32515j], [-0.21271+0.34938j, -0.38853+0.36497j, 0.61467-0.41317j]]) eigen_vals, eigen_vecs = np.linalg.eigh(V) umat = eigen_vecs.T wires = range(len(umat)) qm = QMachine(len(umat)) for i in range(len(umat)): hadamard(q_machine=qm, wires=i) isingzz(q_machine=qm, params=QTensor([0.55]), wires=[0,2]) VQC_BasisRotation(q_machine=qm, wires=wires,unitary_matrix=QTensor(umat,dtype=qm.state.dtype)) print(qm.states) # [[[[ 0.3402686-0.0960063j 0.4140436-0.3069579j] # [ 0.1206574+0.1982292j 0.5662895-0.0949503j]] # # [[-0.1715559-0.1614315j 0.1624039-0.0598041j] # [ 0.0608986-0.1078906j -0.305845 +0.1773662j]]]]
VQC_QuantumPoolingCircuit¶
- pyvqnet.qnn.vqc.VQC_QuantumPoolingCircuit(ignored_wires, sinks_wires, params, q_machine)¶
A quantum circuit that downsamples data.
To reduce the number of qubits in a circuit, pairs of qubits are first created in the system. After initially pairing all qubits, a generalized 2-qubit unitary is applied to each pair of qubits. And after applying the two-qubit unitary, one qubit in each pair of qubits is ignored in the rest of the neural network. :param sources_wires: The source qubit index that will be ignored. :param sinks_wires: The target qubit index to keep. :param params: Input parameters. :param q_machine: Quantum virtual machine device.
- Returns:
pyqpanda QCircuit
Examples:
from pyvqnet.qnn.vqc import VQC_QuantumPoolingCircuit, QMachine, MeasureAll import pyqpanda as pq from pyvqnet import tensor machine = pq.CPUQVM() machine.init_qvm() qlists = machine.qAlloc_many(4) p = tensor.full([6], 0.35) qm = QMachine(4) VQC_QuantumPoolingCircuit(q_machine=qm, ignored_wires=[0, 1], sinks_wires=[2, 3], params=p) m = MeasureAll(obs={"Z1": 1}) exp = m(q_machine=qm) print(exp)
VQC_Purity¶
- class pyvqnet.qnn.vqc.VQC_Purity(state, qubits_idx, num_wires)¶
Calculate the purity on a particular qubit from the state vector.
\[\gamma = \text{Tr}(\rho^2)\]where \(\rho\) is a density matrix. The purity of a normalized quantum state satisfies \(\frac{1}{d} \leq \gamma \leq 1\) , where \(d\) is the dimension of the Hilbert space. The purity of the pure state is 1.
- Parameters:
state – Quantum state obtained from pyqpanda get_qstate()
qubits_idx – Qubit index for which to calculate purity
num_wires – Qubit idx
- Returns:
purity
Example:
from pyvqnet.qnn.vqc import VQC_Purity, rx, ry, cnot, QMachine from pyvqnet.tensor import kfloat64, QTensor x = QTensor([[0.7, 0.4], [1.7, 2.4]], requires_grad=True) qm = QMachine(3) qm.reset_states(2) rx(q_machine=qm, wires=0, params=x[:, [0]]) ry(q_machine=qm, wires=1, params=x[:, [1]]) ry(q_machine=qm, wires=2, params=x[:, [1]]) cnot(q_machine=qm, wires=[0, 1]) cnot(q_machine=qm, wires=[2, 1]) y = VQC_Purity(qm.states, [0, 1], num_wires=3) y.backward() print(y) # [0.9356751 0.875957]
VQC_VarMeasure¶
- class pyvqnet.qnn.vqc.VQC_VarMeasure(q_machine, obs)¶
The variance of the provided observable.
- Parameters:
q_machine – Quantum state obtained from pyqpanda get_qstate()
obs – constructed quantum circuit
- Returns:
variance value
Example:
from pyvqnet.tensor import QTensor from pyvqnet.qnn.vqc import VQC_VarMeasure, rx, cnot, hadamard, QMachine,PauliY x = QTensor([[0.5]], requires_grad=True) qm = QMachine(3) rx(q_machine=qm, wires=0, params=x) var_result = VQC_VarMeasure(q_machine= qm, obs=PauliY(wires=0)) var_result.backward() print(var_result) # [[0.7701511]]
VQC_DensityMatrixFromQstate¶
- class pyvqnet.qnn.vqc.VQC_DensityMatrixFromQstate(state, indices)¶
Computes the density matrix of quantum states over a specific set of qubits.
- Parameters:
state – A 1D list of state vectors. The size of this list should be
(2**N,)
For the number of qubitsN
, qstate should start from 000 -> 111.indices – A list of qubit indices in the considered subsystem.
- Returns:
A density matrix of size “(2**len(indices), 2**len(indices))”.
Example:
from pyvqnet.qnn.vqc import VQC_DensityMatrixFromQstate,rx,ry,cnot,QMachine from pyvqnet.tensor import kfloat64, QTensor x = QTensor([[0.7,0.4],[1.7,2.4]],requires_grad=True) qm = QMachine(3) qm.reset_states(2) rx(q_machine=qm,wires=0,params=x[:,[0]]) ry(q_machine=qm,wires=1,params=x[:,[1]]) ry(q_machine=qm,wires=2,params=x[:,[1]]) cnot(q_machine=qm,wires=[0,1]) cnot(q_machine=qm,wires=[2, 1]) y = VQC_DensityMatrixFromQstate(qm.states,[0,1]) print(y) # [[[0.8155131+0.j 0.1718155+0.j 0. +0.0627175j # 0. +0.2976855j] # [0.1718155+0.j 0.0669081+0.j 0. +0.0244234j # 0. +0.0627175j] # [0. -0.0627175j 0. -0.0244234j 0.0089152+0.j # 0.0228937+0.j ] # [0. -0.2976855j 0. -0.0627175j 0.0228937+0.j # 0.1086637+0.j ]] # # [[0.3362115+0.j 0.1471083+0.j 0. +0.1674582j # 0. +0.3827205j] # [0.1471083+0.j 0.0993662+0.j 0. +0.1131119j # 0. +0.1674582j] # [0. -0.1674582j 0. -0.1131119j 0.1287589+0.j # 0.1906232+0.j ] # [0. -0.3827205j 0. -0.1674582j 0.1906232+0.j # 0.4356633+0.j ]]]
Probability¶
- class pyvqnet.qnn.vqc.Probability(wires, name='')¶
Calculating the probability measurements of quantum circuits on specific bits
- Parameters:
wires – Measure qubit idx.
- Returns:
Measure result Tensor.
Example:
from pyvqnet.qnn.vqc import Probability,rx,ry,cnot,QMachine,rz from pyvqnet.tensor import kfloat64, QTensor x = QTensor([[0.56, 0.1],[0.56, 0.1]],requires_grad=True) qm = QMachine(4) qm.reset_states(2) rz(q_machine=qm,wires=0,params=x[:,[0]]) rz(q_machine=qm,wires=1,params=x[:,[0]]) cnot(q_machine=qm,wires=[0,1]) ry(q_machine=qm,wires=2,params=x[:,[1]]) cnot(q_machine=qm,wires=[0,2]) rz(q_machine=qm,wires=3,params=x[:,[1]]) ma = Probability(wires=1) y =ma(q_machine=qm) # [[1.0000002 0. ] # [1.0000002 0. ]]
MeasureAll¶
- class pyvqnet.qnn.vqc.MeasureAll(obs, name='')¶
Calculate the measurement results of quantum circuits, and support input obs as multiple or single Pauli operators or Hamiltonian quantities.
For example:
{'wires': [0, 1], 'observables': ['x', 'i'],'coefficient':[0.23,-3.5]} or: {'X0': 0.23} or: [{'wires': [0, 2, 3],'observables': ['X', 'Y', 'Z'],'coefficient': [1, 0.5, 0.4]}, {'wires': [0, 1, 2],'observables': ['X', 'Y', 'Z'],'coefficient': [1, 0.5, 0.4]}]
- Parameters:
obs – observable。
- Returns:
output Tensor.
Example:
from pyvqnet.qnn.vqc import MeasureAll,rx,ry,cnot,QMachine,rz from pyvqnet.tensor import kfloat64, QTensor x = QTensor([[0.56, 0.1],[0.56, 0.1]],requires_grad=True) qm = QMachine(4) qm.reset_states(2) rz(q_machine=qm,wires=0,params=x[:,[0]]) rz(q_machine=qm,wires=1,params=x[:,[0]]) cnot(q_machine=qm,wires=[0,1]) ry(q_machine=qm,wires=2,params=x[:,[1]]) cnot(q_machine=qm,wires=[0,2]) rz(q_machine=qm,wires=3,params=x[:,[1]]) obs_list = [{ 'wires': [0, 2, 3], 'observables': ['X', 'Y', 'Z'], 'coefficient': [1, 0.5, 0.4] }, { 'wires': [0, 1, 2], 'observables': ['X', 'Y', 'Z'], 'coefficient': [1, 0.5, 0.4] }] ma = MeasureAll(obs=obs_list) y =ma(q_machine=qm) print(y) # [[0.4000001 0.3980018] # [0.4000001 0.3980018]]
SparseHamiltonian¶
- class pyvqnet.qnn.vqc.SparseHamiltonian(obs, name='')¶
Computes the sparse Hamiltonian of an observation, for example {“observables”:H,”wires”:[0,2,3]}.
- Parameters:
obs – Sparse Hamiltonian, use the tensor.dense_to_csr() function to obtain the sparse format of the dense function.
name – The name of the module, default: “”.
- Returns:
Expected result, QTensor.
Example:
import pyvqnet pyvqnet.utils.set_random_seed(42) from pyvqnet import tensor from pyvqnet.nn import Module from pyvqnet.qnn.vqc import QMachine,CRX,PauliX,paulix,crx,SparseHamiltonian H = tensor.QTensor( [[ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 0.+0.j, -1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [ 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,], [-1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,]],dtype=pyvqnet.kcomplex64) cpu_csr = tensor.dense_to_csr(H) class QModel(Module): def __init__(self, num_wires, dtype,grad_mode=""): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires) self.measure = SparseHamiltonian(obs = {"observables":cpu_csr, "wires":[2, 1, 3, 5]}) def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) paulix(q_machine=self.qm, wires= 0) paulix(q_machine=self.qm, wires = 2) crx(q_machine=self.qm,wires=[0, 1],params=tensor.full((x.shape[0],1),0.1,dtype=pyvqnet.kcomplex64)) crx(q_machine=self.qm,wires=[2, 3],params=tensor.full((x.shape[0],1),0.2,dtype=pyvqnet.kcomplex64)) crx(q_machine=self.qm,wires=[1, 2],params=tensor.full((x.shape[0],1),0.3,dtype=pyvqnet.kcomplex64)) crx(q_machine=self.qm,wires=[2, 4],params=tensor.full((x.shape[0],1),0.3,dtype=pyvqnet.kcomplex64)) crx(q_machine=self.qm,wires=[5, 3],params=tensor.full((x.shape[0],1),0.3,dtype=pyvqnet.kcomplex64)) rlt = self.measure(q_machine=self.qm) return rlt model = QModel(6,pyvqnet.kcomplex64) y = model(tensor.ones([1,1])) print(y) #[0.]
HermitianExpval¶
- class pyvqnet.qnn.vqc.HermitianExpval(obs, name='')¶
Calculate the expectation of a certain Hermitian quantity of a quantum circuit.
- Parameters:
obs – Hermitian quantity.
name – The name of the module, default: “”.
- Returns:
Expected result, QTensor.
Example:
from pyvqnet.qnn.vqc import qcircuit from pyvqnet.qnn.vqc import QMachine, RX, RY, CNOT, PauliX, qmatrix, PauliZ, VQC_RotCircuit,HermitianExpval from pyvqnet.tensor import QTensor, tensor import pyvqnet from pyvqnet.nn import Parameter import numpy as np bsz = 3 H = np.array([[8, 4, 0, -6], [4, 0, 4, 0], [0, 4, 8, 0], [-6, 0, 0, 0]]) class QModel(pyvqnet.nn.Module): def __init__(self, num_wires, dtype): super(QModel, self).__init__() self.rot_param = Parameter((3, )) self.rot_param.copy_value_from(tensor.QTensor([-0.5, 1, 2.3])) self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.rx_layer1 = VQC_RotCircuit self.ry_layer2 = RY(has_params=True, trainable=True, wires=0, init_params=tensor.QTensor([-0.5])) self.xlayer = PauliX(wires=0) self.cnot = CNOT(wires=[0, 1]) self.measure = HermitianExpval(obs = {'wires':(1,0),'observables':tensor.to_tensor(H)}) def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) qcircuit.rx(q_machine=self.qm, wires=0, params=x[:, [1]]) qcircuit.ry(q_machine=self.qm, wires=1, params=x[:, [0]]) self.xlayer(q_machine=self.qm) self.rx_layer1(params=self.rot_param, wire=1, q_machine=self.qm) self.ry_layer2(q_machine=self.qm) self.cnot(q_machine=self.qm) rlt = self.measure(q_machine = self.qm) return rlt input_x = tensor.arange(1, bsz * 2 + 1, dtype=pyvqnet.kfloat32).reshape([bsz, 2]) input_x.requires_grad = True qunatum_model = QModel(num_wires=2, dtype=pyvqnet.kcomplex64) batch_y = qunatum_model(input_x) batch_y.backward() print(batch_y) # [[5.3798223], # [7.1294155], # [0.7028297]]
Commonly used quantum variation circuit templates¶
VQC_HardwareEfficientAnsatz¶
- class pyvqnet.qnn.vqc.VQC_HardwareEfficientAnsatz(n_qubits, single_rot_gate_list, entangle_gate='CNOT', entangle_rules='linear', depth=1)¶
The implementation of Hardware Efficient Ansatz introduced in the paper:Hardware-efficient Variational Quantum Eigensolver for Small Molecules.
- Parameters:
n_qubits – number of qubits.
single_rot_gate_list – A single-qubit turnstile list consists of one or more turnstiles that act on each qubit. Rx, Ry, Rz are currently supported.
entangle_gate – Nonparametric entanglement gates. Support CNOT, CZ. Default: CNOT.
entangle_rules – How to use entanglement gates in circuits.
linear
means that the entanglement gate will act on every adjacent qubit.all
means that the entanglement gate will act on any two qbuits. Default:linear
.depth – Ansatz depth, default: 1.
Example:
from pyvqnet.nn import Module,Linear,ModuleList from pyvqnet.qnn.vqc.qcircuit import VQC_HardwareEfficientAnsatz,RZZ,RZ from pyvqnet.qnn.vqc import Probability,QMachine from pyvqnet import tensor class QM(Module): def __init__(self, name=""): super().__init__(name) self.linearx = Linear(4,2) self.ansatz = VQC_HardwareEfficientAnsatz(4, ["rx", "RY", "rz"], entangle_gate="cnot", entangle_rules="linear", depth=2) self.encode1 = RZ(wires=0) self.encode2 = RZ(wires=1) self.measure = Probability(wires=[0,2]) self.device = QMachine(4) def forward(self, x, *args, **kwargs): self.device.reset_states(x.shape[0]) y = self.linearx(x) self.encode1(params = y[:, [0]],q_machine = self.device,) self.encode2(params = y[:, [1]],q_machine = self.device,) self.ansatz(q_machine =self.device) return self.measure(q_machine =self.device) bz =3 inputx = tensor.arange(1.0,bz*4+1).reshape([bz,4]) inputx.requires_grad= True qlayer = QM() y = qlayer(inputx) y.backward() print(y) # [[0.3075959 0.2315064 0.2491432 0.2117545] # [0.3075958 0.2315062 0.2491433 0.2117546] # [0.3075958 0.2315062 0.2491432 0.2117545]]
VQC_BasicEntanglerTemplate¶
- class pyvqnet.qnn.vqc.VQC_BasicEntanglerTemplate(num_layer=1, num_qubits=1, rotation='RX', initial=None, dtype=None)¶
A layer consisting of a single-parameter single-qubit rotation on each qubit, followed by a closed chain or ring combination of multiple CNOT gates.
A CNOT gate ring connects each qubit to its neighbors, with the last qubit considered to be a neighbor of the first qubit.
- Parameters:
num_layer – The number of qubit circuit layers.
num_qubits – The number of qubits, defaults to 1.
rotation – With single-parameter single-qubit gates,
RX
is used as the default.
Example:
from pyvqnet.nn import Module, Linear, ModuleList from pyvqnet.qnn.vqc.qcircuit import VQC_BasicEntanglerTemplate, RZZ, RZ from pyvqnet.qnn.vqc import Probability, QMachine from pyvqnet import tensor class QM(Module): def __init__(self, name=""): super().__init__(name) self.ansatz = VQC_BasicEntanglerTemplate(2, 4, "rz", initial=tensor.ones([1, 1])) self.measure = Probability(wires=[0, 2]) self.device = QMachine(4) def forward(self,x, *args, **kwargs): self.ansatz(q_machine=self.device) return self.measure(q_machine=self.device) bz = 1 inputx = tensor.arange(1.0, bz * 4 + 1).reshape([bz, 4]) qlayer = QM() y = qlayer(inputx) y.backward() print(y) # [[1.0000002 0. 0. 0. ]]
VQC_StronglyEntanglingTemplate¶
- class pyvqnet.qnn.vqc.VQC_StronglyEntanglingTemplate(weights=None, num_qubits=1, ranges=None)¶
A layer consisting of a single qubit rotation and an entangler, see circuit-centric classifier design.
The parameter
weights
contains the weights for each layer. Thus it follows that the number of layers \(L\) is equal to the first dimension ofweights
.It consists of 2-qubit CNOT gates acting on :math: M qubits, \(i = 1,...,M\). The second qubit label for each gate is given by the formula \((i+r)\mod M\), where \(r\) is a hyperparameter called
range
, and :math: 0 < r < M.- Parameters:
weights – Weight tensor of shape
(L, M, 3)
, default: None, use a random tensor of shape(1,1,3)
.num_qubits – The number of qubits, default: 1.
ranges – Sequence of hyperparameters that determine the ranges of each subsequent layer; default: None, use \(r=l \ mod M\) as the value of ranges.
Example:
from pyvqnet.nn import Module from pyvqnet.qnn.vqc.qcircuit import VQC_StronglyEntanglingTemplate from pyvqnet.qnn.vqc import Probability, QMachine from pyvqnet import tensor class QM(Module): def __init__(self, name=""): super().__init__(name) self.ansatz = VQC_StronglyEntanglingTemplate(2, 4, None, initial=tensor.ones([1, 1])) self.measure = Probability(wires=[0, 1]) self.device = QMachine(4) def forward(self,x, *args, **kwargs): self.ansatz(q_machine=self.device) return self.measure(q_machine=self.device) bz = 1 inputx = tensor.arange(1.0, bz * 4 + 1).reshape([bz, 4]) qlayer = QM() y = qlayer(inputx) y.backward() print(y) # [[0.3745951 0.154298 0.059156 0.4119509]]
VQC_QuantumEmbedding¶
- class pyvqnet.qnn.VQC_QuantumEmbedding(qubits, machine, num_repetitions_input, depth_input, num_unitary_layers, num_repetitions)¶
Use RZ,RY,RZ to create variational quantum circuits that encode classical data into quantum states. Reference Quantum embeddings for machine learning. After the class is initialized, its member function
compute_circuit
is a running function, which can be input as a parameter. TheQuantumLayerV2
class constitutes a layer of the quantum machine learning model.- Parameters:
qubits – Qubits requested using pyqpanda.
machine – Quantum virtual machine requested by pyqpanda.
num_repetitions_input – Number of repetitions to encode input in submodules.
depth_input – The feature dimension of the input data.
num_unitary_layers – The number of repetitions of the variable quantum gates in each submodule.
num_repetitions – The number of repetitions for the submodule.
Example:
from pyvqnet.nn import Module from pyvqnet.qnn.vqc.qcircuit import VQC_QuantumEmbedding from pyvqnet.qnn.vqc import QMachine,MeasureAll from pyvqnet import tensor import pyvqnet depth_input = 2 num_repetitions = 2 num_repetitions_input = 2 num_unitary_layers = 2 nq = depth_input * num_repetitions_input bz = 12 class QM(Module): def __init__(self, name=""): super().__init__(name) self.ansatz = VQC_QuantumEmbedding(num_repetitions_input, depth_input, num_unitary_layers, num_repetitions, pyvqnet.kfloat64, initial=tensor.full([1],12.0)) self.measure = MeasureAll(obs={f"Z{nq-1}":1}) self.device = QMachine(nq,dtype=pyvqnet.kcomplex128) def forward(self, x, *args, **kwargs): self.device.reset_states(x.shape[0]) self.ansatz(x,q_machine=self.device) return self.measure(q_machine=self.device) inputx = tensor.arange(1.0, bz * depth_input + 1, dtype=pyvqnet.kfloat64).reshape([bz, depth_input]) qlayer = QM() y = qlayer(inputx) y.backward() print(y) # [[-0.2539548] # [-0.1604787] # [ 0.1492931] # [-0.1711956] # [-0.1577133] # [ 0.1396999] # [ 0.016864 ] # [-0.0893069] # [ 0.1897014] # [ 0.0941301] # [ 0.0550722] # [ 0.2408579]]
Other functions¶
QuantumLayerAdjoint¶
- class pyvqnet.qnn.vqc.QuantumLayerAdjoint(general_module: pyvqnet.nn.Module, q_machine: QMachine, name='')¶
An automatically differentiated QuantumLayer layer that uses adjoint matrix method for gradient calculation, refer to Efficient calculation of gradients in classical simulations of variational quantum algorithms.
- Parameters:
general_module – A pyvqnet.nn.Module instance built using only the pyvqnet.qnn.vqc lower quantum circuit interface.
q_machine – comes from the QMachine defined in general_module.
name – The name of this layer, the default is “”.
Note
QMachine for general_module should set grad_method = “adjoint”. Currently, the following parametric logic gates are supported: RX, RY, RZ, PhaseShift, RXX, RYY, RZZ, RZX, U1, U2, U3 and other variational circuits without parametric logic gates.
Example:
from pyvqnet import tensor from pyvqnet.qnn.vqc import QuantumLayerAdjoint, QMachine, RX, RY, CNOT, PauliX, qmatrix, PauliZ, T, MeasureAll, RZ, VQC_RotCircuit, VQC_HardwareEfficientAnsatz import pyvqnet class QModel(pyvqnet.nn.Module): def __init__(self, num_wires, dtype, grad_mode=""): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype, grad_mode=grad_mode) self.rx_layer = RX(has_params=True, trainable=False, wires=0) self.ry_layer = RY(has_params=True, trainable=False, wires=1) self.rz_layer = RZ(has_params=True, trainable=False, wires=1) self.rz_layer2 = RZ(has_params=True, trainable=True, wires=1) self.rot = VQC_HardwareEfficientAnsatz(6, ["rx", "RY", "rz"], entangle_gate="cnot", entangle_rules="linear", depth=5) self.tlayer = T(wires=1) self.cnot = CNOT(wires=[0, 1]) self.measure = MeasureAll(obs={ 'wires': [1], 'observables': ['x'], 'coefficient': [1] }) def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) self.rx_layer(params=x[:, [0]], q_machine=self.qm) self.cnot(q_machine=self.qm) self.ry_layer(params=x[:, [1]], q_machine=self.qm) self.tlayer(q_machine=self.qm) self.rz_layer(params=x[:, [2]], q_machine=self.qm) self.rz_layer2(q_machine=self.qm) self.rot(q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt input_x = tensor.QTensor([[0.1, 0.2, 0.3]]) input_x = tensor.broadcast_to(input_x, [40, 3]) input_x.requires_grad = True qunatum_model = QModel(num_wires=6, dtype=pyvqnet.kcomplex64, grad_mode="adjoint") adjoint_model = QuantumLayerAdjoint(qunatum_model, qunatum_model.qm) batch_y = adjoint_model(input_x) batch_y.backward() # [[-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047]]
QuantumLayerES¶
- class pyvqnet.qnn.vqc.QuantumLayerES(general_module: nn.Module, q_machine: QMachine, name='', sigma=np.pi / 24)¶
Automatically Differentiable QuantumLayer Layer for Gradient Calculation According to Evolutionary Strategies, refer to Learning to learn with an evolutionary strategy Learning to learn with an evolutionary strategy .
- param general_module:
An instance of pyvqnet.nn.QModule built using only the quantum line interface under pyvqnet.qnn.vqc.
- param q_machine:
The QMachine from the general_module definition.
- param name:
The name of the layer, defaults to “”.
- param sigma:
The sampling variance of the multivariate sigma distribution.
Note
The QMachine for general_module should have grad_method = “ES”.
Variable division lines consisting of the following parametric logic gates RX, RY, RZ, PhaseShift, RXX, RYY, RZZ, RZX, U1, U2, U3, and other non-parametric logic gates are supported at present.
Example:
from pyvqnet import tensor from pyvqnet.qnn.vqc import QuantumLayerES, QMachine, RX, RY, CNOT, T, MeasureAll, RZ, VQC_HardwareEfficientAnsatz import pyvqnet class QModel(pyvqnet.nn.Module): def __init__(self, num_wires, dtype, grad_mode=""): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype, grad_mode=grad_mode) self.rx_layer = RX(has_params=True, trainable=False, wires=0) self.ry_layer = RY(has_params=True, trainable=False, wires=1) self.rz_layer = RZ(has_params=True, trainable=False, wires=1) self.rz_layer2 = RZ(has_params=True, trainable=True, wires=1) self.rot = VQC_HardwareEfficientAnsatz(6, ["rx", "RY", "rz"], entangle_gate="cnot", entangle_rules="linear", depth=5) self.tlayer = T(wires=1) self.cnot = CNOT(wires=[0, 1]) self.measure = MeasureAll(obs = { 'wires': [1], 'observables': ['x'], 'coefficient': [1] }) def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) self.rx_layer(params=x[:, [0]], q_machine=self.qm) self.cnot(q_machine=self.qm) self.ry_layer(params=x[:, [1]], q_machine=self.qm) self.tlayer(q_machine=self.qm) self.rz_layer(params=x[:, [2]], q_machine=self.qm) self.rz_layer2(q_machine=self.qm) self.rot(q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt input_x = tensor.QTensor([[0.1, 0.2, 0.3]]) input_x = tensor.broadcast_to(input_x, [40, 3]) input_x.requires_grad = True qunatum_model = QModel(num_wires=6, dtype=pyvqnet.kcomplex64, grad_mode="ES") ES_model = QuantumLayerES(qunatum_model, qunatum_model.qm) batch_y = ES_model(input_x) batch_y.backward() # [[-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047] # [-0.0511386 -0.2238654 0.0133047]]
vqc_to_originir_list¶
- pyvqnet.qnn.vqc.vqc_to_originir_list(vqc_model: pyvqnet.nn.Module)¶
Convert VQNet vqc module to originIR .
vqc_model should run the forward function before this function to get the input data. If the input data is batch data. For each input it will return multiple IR strings.
- Parameters:
vqc_model – VQNet vqc module, which should be run forward first.
- Returns:
originIR string or originIR string list.
Example:
import pyvqnet import pyvqnet.tensor as tensor from pyvqnet.qnn.vqc import * from pyvqnet.nn import Module class QModel(Module): def __init__(self, num_wires, dtype,grad_mode=""): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype,grad_mode=grad_mode,save_ir=True) self.rx_layer = RX(has_params=True, trainable=False, wires=0) self.ry_layer = RY(has_params=True, trainable=False, wires=1) self.rz_layer = RZ(has_params=True, trainable=False, wires=1) self.u1 = U1(has_params=True,trainable=True,wires=[2]) self.u2 = U2(has_params=True,trainable=True,wires=[3]) self.u3 = U3(has_params=True,trainable=True,wires=[1]) self.i = I(wires=[3]) self.s = S(wires=[3]) self.x1 = X1(wires=[3]) self.y1 = Y1(wires=[3]) self.z1 = Z1(wires=[3]) self.x = PauliX(wires=[3]) self.y = PauliY(wires=[3]) self.z = PauliZ(wires=[3]) self.swap = SWAP(wires=[2,3]) self.cz = CZ(wires=[2,3]) self.cr = CR(has_params=True,trainable=True,wires=[2,3]) self.rxx = RXX(has_params=True,trainable=True,wires=[2,3]) self.rzz = RYY(has_params=True,trainable=True,wires=[2,3]) self.ryy = RZZ(has_params=True,trainable=True,wires=[2,3]) self.rzx = RZX(has_params=True, trainable=False, wires=[2,3]) self.toffoli = Toffoli(wires=[2,3,4],use_dagger=True) #self.rz_layer2 = RZ(has_params=True, trainable=True, wires=1) self.h =Hadamard(wires=[1]) self.rot = VQC_HardwareEfficientAnsatz(6, ["rx", "RY", "rz"], entangle_gate="cnot", entangle_rules="linear", depth=5) self.iSWAP = iSWAP(True,True,wires=[0,2]) self.tlayer = T(wires=1) self.cnot = CNOT(wires=[0, 1]) self.measure = MeasureAll(obs={ 'wires': [1], 'observables': ['x'], 'coefficient': [1] }) def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) self.i(q_machine=self.qm) self.s(q_machine=self.qm) self.swap(q_machine=self.qm) self.cz(q_machine=self.qm) self.x(q_machine=self.qm) self.x1(q_machine=self.qm) self.y(q_machine=self.qm) self.y1(q_machine=self.qm) self.z(q_machine=self.qm) self.z1(q_machine=self.qm) self.ryy(q_machine=self.qm) self.rxx(q_machine=self.qm) self.rzz(q_machine=self.qm) self.rzx(q_machine=self.qm,params = x[:,[1]]) self.cr(q_machine=self.qm) self.u1(q_machine=self.qm) self.u2(q_machine=self.qm) self.u3(q_machine=self.qm) self.rx_layer(params = x[:,[0]], q_machine=self.qm) self.cnot(q_machine=self.qm) self.h(q_machine=self.qm) self.iSWAP(q_machine=self.qm) self.ry_layer(params = x[:,[1]], q_machine=self.qm) self.tlayer(q_machine=self.qm) self.rz_layer(params = x[:,[2]], q_machine=self.qm) self.toffoli(q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt input_x = tensor.QTensor([[0.1, 0.2, 0.3]]) input_x = tensor.broadcast_to(input_x,[2,3]) input_x.requires_grad = True qunatum_model = QModel(num_wires=6, dtype=pyvqnet.kcomplex64) batch_y = qunatum_model(input_x) batch_y.backward() ll = vqc_to_originir_list(qunatum_model) from pyqpanda import CPUQVM,convert_originir_str_to_qprog,convert_qprog_to_originir for l in ll : print(l) machine = CPUQVM() machine.init_qvm() prog, qv, cv = convert_originir_str_to_qprog(l, machine) # QINIT 6 # CREG 6 # I q[3] # S q[3] # SWAP q[2],q[3] # CZ q[2],q[3] # X q[3] # X1 q[3] # Y q[3] # Y1 q[3] # Z q[3] # Z1 q[3] # ISWAPTHETA q[2],q[3],(0.9916799664497375) # ISWAPTHETA q[2],q[3],(5.76633358001709) # ISWAPTHETA q[2],q[3],(0.45163241028785706) # ISWAPTHETA q[2],q[3],(0.20000000298023224) # CR q[2],q[3],(6.129976272583008) # U1 q[2],(5.1650896072387695) # U2 q[3],(0.672031581401825,4.012712001800537) # U3 q[1],(1.2062039375305176,5.261843204498291,3.8955893516540527) # RX q[0],(0.10000000149011612) # CNOT q[0],q[1] # H q[1] # ISWAPTHETA q[0],q[2],(3.298604726791382) # RY q[1],(0.20000000298023224) # T q[1] # RZ q[1],(0.30000001192092896) # DAGGER # TOFFOLI q[2],q[3],q[4] # ENDDAGGER # {'000000': 0.305050924775766, '000001': 0.0009450719636359255, '000010': 0.12846598944342266, '000011': 0.002890791669957549, '000100': 0.14294840895133598, '000101': 0.0003942920949765717, '000110': 0.05759773036056239, '000111': 0.00011479719450177659, '001000': 0.11075158748630215, '001001': 0.002333114548298535, '001010': 0.04664077736960161, '001011': 0.002162103757935423, '001100': 0.0, '001101': 0.0, '001110': 0.0, '001111': 0.0, '010000': 0.0, '010001': 0.0, '010010': 0.0, '010011': 0.0, '010100': 0.0, '010101': 0.0, '010110': 0.0, '010111': 0.0, '011000': 0.0, '011001': 0.0, '011010': 0.0, '011011': 0.0, '011100': 0.1410248245365744, '011101': 0.0003942920949765718, '011110': 0.05817049655765043, '011111': 0.0001147971945017766, '100000': 0.0, '100001': 0.0, '100010': 0.0, '100011': 0.0, '100100': 0.0, '100101': 0.0, '100110': 0.0, '100111': 0.0, '101000': 0.0, '101001': 0.0, '101010': 0.0, '101011': 0.0, '101100': 0.0, '101101': 0.0, '101110': 0.0, '101111': 0.0, '110000': 0.0, '110001': 0.0, '110010': 0.0, '110011': 0.0, '110100': 0.0, '110101': 0.0, '110110': 0.0, '110111': 0.0, '111000': 0.0, '111001': 0.0, '111010': 0.0, '111011': 0.0, '111100': 0.0, '111101': 0.0, '111110': 0.0, '111111': 0.0} # QINIT 6 # CREG 6 # I q[3] # S q[3] # SWAP q[2],q[3] # CZ q[2],q[3] # X q[3] # X1 q[3] # Y q[3] # Y1 q[3] # Z q[3] # Z1 q[3] # ISWAPTHETA q[2],q[3],(0.9916799664497375) # ISWAPTHETA q[2],q[3],(5.76633358001709) # ISWAPTHETA q[2],q[3],(0.45163241028785706) # ISWAPTHETA q[2],q[3],(0.20000000298023224) # CR q[2],q[3],(6.129976272583008) # U1 q[2],(5.1650896072387695) # U2 q[3],(0.672031581401825,4.012712001800537) # U3 q[1],(1.2062039375305176,5.261843204498291,3.8955893516540527) # RX q[0],(0.10000000149011612) # CNOT q[0],q[1] # H q[1] # ISWAPTHETA q[0],q[2],(3.298604726791382) # RY q[1],(0.20000000298023224) # T q[1] # RZ q[1],(0.30000001192092896) # DAGGER # TOFFOLI q[2],q[3],q[4] # ENDDAGGER # {'000000': 0.305050924775766, '000001': 0.0009450719636359255, '000010': 0.12846598944342266, '000011': 0.002890791669957549, '000100': 0.14294840895133598, '000101': 0.0003942920949765717, '000110': 0.05759773036056239, '000111': 0.00011479719450177659, '001000': 0.11075158748630215, '001001': 0.002333114548298535, '001010': 0.04664077736960161, '001011': 0.002162103757935423, '001100': 0.0, '001101': 0.0, '001110': 0.0, '001111': 0.0, '010000': 0.0, '010001': 0.0, '010010': 0.0, '010011': 0.0, '010100': 0.0, '010101': 0.0, '010110': 0.0, '010111': 0.0, '011000': 0.0, '011001': 0.0, '011010': 0.0, '011011': 0.0, '011100': 0.1410248245365744, '011101': 0.0003942920949765718, '011110': 0.05817049655765043, '011111': 0.0001147971945017766, '100000': 0.0, '100001': 0.0, '100010': 0.0, '100011': 0.0, '100100': 0.0, '100101': 0.0, '100110': 0.0, '100111': 0.0, '101000': 0.0, '101001': 0.0, '101010': 0.0, '101011': 0.0, '101100': 0.0, '101101': 0.0, '101110': 0.0, '101111': 0.0, '110000': 0.0, '110001': 0.0, '110010': 0.0, '110011': 0.0, '110100': 0.0, '110101': 0.0, '110110': 0.0, '110111': 0.0, '111000': 0.0, '111001': 0.0, '111010': 0.0, '111011': 0.0, '111100': 0.0, '111101': 0.0, '111110': 0.0, '111111': 0.0}
originir_to_vqc¶
- pyvqnet.qnn.vqc.originir_to_vqc(originir, tmp='code_tmp.py', verbose=False)¶
Parse originIR into vqc model code. The code creates a variational quantum circuit pyvqnet.nn.Module without Measure, and returns the state vector form of the quantum state, such as [b,2,…,2]. This function will generate a code file defining the corresponding VQNet model in “./origin_ir_gen_code/” + tmp + “.py”.
- Parameters:
originir – Original IR.
tmp – code file name, default
code_tmp.py
.verbose – If display generated code, default = False
- Returns:
Generate runnable code.
Example:
from pyvqnet.qnn.vqc import originir_to_vqc ss = "QINIT 3\nCREG 3\nH q[1]" Z = originir_to_vqc(ss,verbose=True) exec(Z) m =Exported_Model() print(m(2)) # from pyvqnet.nn import Module # from pyvqnet.tensor import QTensor # from pyvqnet.qnn.vqc import * # class Exported_Model(Module): # def __init__(self, name=""): # super().__init__(name) # self.q_machine = QMachine(num_wires=3) # self.H_0 = Hadamard(wires=1, use_dagger = False) # def forward(self, x, *args, **kwargs): # x = self.H_0(q_machine=self.q_machine) # return self.q_machine.states # [[[[0.7071068+0.j 0. +0.j] # [0.7071068+0.j 0. +0.j]] # [[0. +0.j 0. +0.j] # [0. +0.j 0. +0.j]]]]
model_summary¶
- pyvqnet.model_summary(vqc_module)¶
Print information about classical layer and quantum gate operators registered in vqc_module.
- Parameters:
vqc_module – vqc module
- Returns:
summary string
Example:
from pyvqnet.qnn.vqc import QMachine, RX, RY, CNOT, PauliX, qmatrix, PauliZ,MeasureAll from pyvqnet.tensor import QTensor, tensor,kcomplex64 importpyvqnet from pyvqnet.nn import LSTM,Linear from pyvqnet import model_summary class QModel(pyvqnet.nn.Module): def __init__(self, num_wires, dtype): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.rx_layer1 = RX(has_params=True, trainable=True, wires=1, init_params=tensor.QTensor([0.5])) self.ry_layer2 = RY(has_params=True, trainable=True, wires=0, init_params=tensor.QTensor([-0.5])) self.xlayer = PauliX(wires=0) self.cnot = CNOT(wires=[0, 1]) self.measure = MeasureAll(obs=PauliZ) self.linear = Linear(24,2) self.lstm =LSTM(23,5) def forward(self, x, *args, **kwargs): return super().forward(x, *args, **kwargs) Z = QModel(4,kcomplex64) print(model_summary(Z)) # ###################QModel Summary###################### # classic layers: {'Linear': 1, 'LSTM': 1} # total classic parameters: 650 # ========================================= # qubits num: 0 # gates: {'RX': 1, 'RY': 1, 'PauliX': 1, 'CNOT': 1} # total quantum gates: 4 # total quantum parameter gates: 2 # total quantum parameters: 2 # #######################################################
QNG¶
- class pyvqnet.qnn.vqc.qng.QNG(qmodel, stepsize=0.01)¶
Quantum machine learning models generally use the gradient descent method to optimize parameters in variable quantum logic circuits. The formula of the classic gradient descent method is as follows:
\[\theta_{t+1} = \theta_t -\eta \nabla \mathcal{L}(\theta),\]Essentially, at each iteration, we will calculate the direction of the steepest gradient drop in the parameter space as the direction of parameter change. In any direction in space, the speed of descent in the local range is not as fast as that of the negative gradient direction. In different spaces, the derivation of the direction of steepest descent is dependent on the norm of parameter differentiation - the distance metric. The distance metric plays a central role here, Different metrics result in different directions of steepest descent. For the Euclidean space where the parameters in the classical optimization problem are located, the direction of the steepest descent is the direction of the negative gradient. Even so, at each step of parameter optimization, as the loss function changes with parameters, its parameter space is transformed. Make it possible to find another better distance norm.
Quantum natural gradient method draws on concepts from classical natural gradient method Amari , We instead view the optimization problem as a probability distribution of possible output values for a given input (i.e., maximum likelihood estimation), a better approach is in the distribution Gradient descent is performed in the space, which is dimensionless and invariant with respect to the parameterization. Therefore, regardless of the parameterization, each optimization step will always choose the optimal step size for each parameter. In quantum machine learning tasks, the quantum state space has a unique invariant metric tensor called the Fubini-Study metric tensor \(g_{ij}\). This tensor converts the steepest descent in the quantum circuit parameter space to the steepest descent in the distribution space. The formula for the quantum natural gradient is as follows:
\[\theta_{t+1} = \theta_t - \eta g^{+}(\theta_t)\nabla \mathcal{L}(\theta),\]where \(g^{+}\) is the pseudo-inverse.
wrapper_calculate_qng is a decorator that needs to be added to the forward function of the model to be calculated for the quantum natural gradient. Only parameters of type Parameter registered with the model are optimized.
- Parameters:
qmodel – Quantum variational circuit model, you need to use wrapper_calculate_qng as the decorator of the forward function.
stepsize – The step size of the gradient descent method, the default is 0.01.
Note
Only tested on non-batch data. Only purely variational quantum circuits are supported. step() will update the gradients of the input and parameters. step() only updates the numerical values of the model parameters.
Example:
from pyvqnet.qnn.vqc import QMachine, RX, RY, RZ, CNOT, rz, PauliX, qmatrix, PauliZ, Probability, rx, ry, MeasureAll, U2 from pyvqnet.tensor import QTensor, tensor import pyvqnet import numpy as np from pyvqnet.qnn.vqc import wrapper_calculate_qng class QModel(pyvqnet.nn.Module): def __init__(self, num_wires, dtype): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.rz_layer1 = RZ(has_params=True, trainable=False, wires=0) self.rz_layer2 = RZ(has_params=True, trainable=False, wires=1) self.u2_layer1 = U2(has_params=True, trainable=False, wires=0) self.l_train1 = RY(has_params=True, trainable=True, wires=1) self.l_train1.params.init_from_tensor( QTensor([333], dtype=pyvqnet.kfloat32)) self.l_train2 = RX(has_params=True, trainable=True, wires=2) self.l_train2.params.init_from_tensor( QTensor([4444], dtype=pyvqnet.kfloat32)) self.xlayer = PauliX(wires=0) self.cnot01 = CNOT(wires=[0, 1]) self.cnot12 = CNOT(wires=[1, 2]) self.measure = MeasureAll(obs={'Y0': 1}) @wrapper_calculate_qng def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) ry(q_machine=self.qm, wires=0, params=np.pi / 4) ry(q_machine=self.qm, wires=1, params=np.pi / 3) ry(q_machine=self.qm, wires=2, params=np.pi / 7) self.rz_layer1(q_machine=self.qm, params=x[:, [0]]) self.rz_layer2(q_machine=self.qm, params=x[:, [1]]) self.u2_layer1(q_machine=self.qm, params=x[:, [3, 4]]) # self.cnot01(q_machine=self.qm) self.cnot12(q_machine=self.qm) ry(q_machine=self.qm, wires=0, params=np.pi / 7) self.l_train1(q_machine=self.qm) self.l_train2(q_machine=self.qm) #rx(q_machine=self.qm, wires=2, params=x[:, [3]]) rz(q_machine=self.qm, wires=1, params=x[:, [2]]) ry(q_machine=self.qm, wires=0, params=np.pi / 7) rz(q_machine=self.qm, wires=1, params=x[:, [2]]) self.cnot01(q_machine=self.qm) self.cnot12(q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt qmodel = QModel(3, pyvqnet.kcomplex64) x = QTensor([[1111.0, 2222, 444, 55, 666]]) qng = pyvqnet.qnn.vqc.QNG(qmodel,0.01) qng.step(x) print(qmodel.parameters()) #[[[333.0084]], [[4443.9985]]]
wrapper_single_qubit_op_fuse¶
- pyvqnet.qnn.vqc.wrapper_single_qubit_op_fuse(f)¶
A decorator for fusing single-bit operations into Rot operations.
Note
f is the forward function of the module, and the forward function of the model needs to be run once to take effect. The model defined here inherits from pyvqnet.qnn.vqc.QModule, which is a subclass of pyvqnet.nn.Module.
Example:
from pyvqnet import tensor from pyvqnet.qnn.vqc import QMachine, Operation, apply_unitary_bmm from pyvqnet import kcomplex128 from pyvqnet.tensor import adjoint import numpy as np from pyvqnet.qnn.vqc import single_qubit_ops_fuse, wrapper_single_qubit_op_fuse, QModule,op_history_summary from pyvqnet.qnn.vqc import QMachine, RX, RY, CNOT, PauliX, qmatrix, PauliZ, T, MeasureAll, RZ from pyvqnet.tensor import QTensor, tensor import pyvqnet import numpy as np from pyvqnet.utils import set_random_seed set_random_seed(42) class QModel(QModule): def __init__(self, num_wires, dtype): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.rx_layer = RX(has_params=True, trainable=False, wires=0, dtype=dtype) self.ry_layer = RY(has_params=True, trainable=False, wires=1, dtype=dtype) self.rz_layer = RZ(has_params=True, trainable=False, wires=1, dtype=dtype) self.rz_layer2 = RZ(has_params=True, trainable=False, wires=1, dtype=dtype) self.tlayer = T(wires=1) self.cnot = CNOT(wires=[0, 1]) self.measure = MeasureAll(obs={ 'wires': [1], 'observables': ['x'], 'coefficient': [1] }) @wrapper_single_qubit_op_fuse def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) self.rx_layer(params=x[:, [0]], q_machine=self.qm) self.cnot(q_machine=self.qm) self.ry_layer(params=x[:, [1]], q_machine=self.qm) self.tlayer(q_machine=self.qm) self.rz_layer(params=x[:, [2]], q_machine=self.qm) self.rz_layer2(params=x[:, [3]], q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt input_x = tensor.QTensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.2, 0.3, 0.4]], dtype=pyvqnet.kfloat64) input_xt = tensor.tile(input_x, (100, 1)) input_xt.requires_grad = True qunatum_model = QModel(num_wires=2, dtype=pyvqnet.kcomplex128) batch_y = qunatum_model(input_xt) print(op_history_summary(qunatum_model.qm.op_history)) # ###################Summary####################### # qubits num: 2 # gates: {'rot': 2, 'cnot': 1} # total gates: 3 # total parameter gates: 2 # total parameters: 6 # #################################################
wrapper_commute_controlled¶
- pyvqnet.qnn.vqc.wrapper_commute_controlled(f, direction='right')¶
Decorators for controlled door swapping This is a quantum transformation used to move swappable gates in front of the control and target bits of the controlled operation. The diagonal gates on either side of the control bit do not affect the result of the controlled gate; therefore, we can push all single-bit gates acting on the first bit together to the right (and fuse them if necessary). Similarly, X-gates are interchangeable with the target bits of CNOT and Toffoli (as are PauliY and CRY). We can use this transformation to push single-bit gates as deep into controlled operation as possible.
Note
f is the forward function of the module, and the forward function of the model needs to be run once to take effect. The model defined here inherits from pyvqnet.qnn.vqc.QModule, which is a subclass of pyvqnet.nn.Module.
- Parameters:
f – forward function.
direction – The direction to move the single-bit gate, the optional value is “left” or “right”, the default is “right”.
Example:
from pyvqnet import tensor from pyvqnet.qnn.vqc import QMachine from pyvqnet import kcomplex128 from pyvqnet.tensor import adjoint import numpy as np from pyvqnet.qnn.vqc import wrapper_commute_controlled, pauliy, QModule,op_history_summary from pyvqnet.qnn.vqc import QMachine, RX, RY, CNOT, S, CRY, PauliZ, PauliX, T, MeasureAll, RZ, CZ, PhaseShift, Toffoli, cnot, cry, toffoli from pyvqnet.tensor import QTensor, tensor import pyvqnet import numpy as np from pyvqnet.utils import set_random_seed from pyvqnet.qnn import expval, QuantumLayerV2 import time from functools import partial set_random_seed(42) class QModel(QModule): def __init__(self, num_wires, dtype): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.cz = CZ(wires=[0, 2]) self.paulix = PauliX(wires=2) self.s = S(wires=0) self.ps = PhaseShift(has_params=True, trainable= True, wires=0, dtype=dtype) self.t = T(wires=0) self.rz = RZ(has_params=True, wires=1, dtype=dtype) self.measure = MeasureAll(obs={ 'wires': [0], 'observables': ['z'], 'coefficient': [1] }) @partial(wrapper_commute_controlled, direction="left") def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) self.cz(q_machine=self.qm) self.paulix(q_machine=self.qm) self.s(q_machine=self.qm) cnot(q_machine=self.qm, wires=[0, 1]) pauliy(q_machine=self.qm, wires=1) cry(q_machine=self.qm, params=1 / 2, wires=[0, 1]) self.ps(q_machine=self.qm) toffoli(q_machine=self.qm, wires=[0, 1, 2]) self.t(q_machine=self.qm) self.rz(q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt import pyvqnet import pyvqnet.tensor as tensor input_x = tensor.QTensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.2, 0.3, 0.4]], dtype=pyvqnet.kfloat64) input_xt = tensor.tile(input_x, (100, 1)) input_xt.requires_grad = True qunatum_model = QModel(num_wires=3, dtype=pyvqnet.kcomplex128) batch_y = qunatum_model(input_xt) for d in qunatum_model.qm.op_history: name = d["name"] wires = d["wires"] p = d["params"] print(f"name: {name} wires: {wires}, params = {p}") # name: s wires: (0,), params = None # name: phaseshift wires: (0,), params = [[4.744782]] # name: t wires: (0,), params = None # name: cz wires: (0, 2), params = None # name: paulix wires: (2,), params = None # name: cnot wires: (0, 1), params = None # name: pauliy wires: (1,), params = None # name: cry wires: (0, 1), params = [[0.5]] # name: rz wires: (1,), params = [[4.7447823]] # name: toffoli wires: (0, 1, 2), params = None # name: MeasureAll wires: [0], params = None
wrapper_merge_rotations¶
- pyvqnet.qnn.vqc.wrapper_merge_rotations(f)¶
- Merge decorators for turnstiles of the same type, including “rx”, “ry”, “rz”, “phaseshift”, “crx”, “cry”, “crz”, “controlledphaseshift”, “isingxx”,
“isingyy”, “isingzz”, “rot”.
Note
f is the forward function of the module, and the forward function of the model needs to be run once to take effect. The model defined here inherits from pyvqnet.qnn.vqc.QModule, which is a subclass of pyvqnet.nn.Module.
- Parameters:
f – forward function.
Example:
import pyvqnet from pyvqnet.tensor import tensor from pyvqnet import tensor from pyvqnet.qnn.vqc import QMachine,op_history_summary from pyvqnet import kcomplex128 from pyvqnet.tensor import adjoint import numpy as np from pyvqnet.qnn.vqc import * from pyvqnet.qnn.vqc import QModule from pyvqnet.tensor import QTensor, tensor import pyvqnet import numpy as np from pyvqnet.utils import set_random_seed set_random_seed(42) class QModel(QModule): def __init__(self, num_wires, dtype): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.measure = MeasureAll(obs={ 'wires': [0], 'observables': ['z'], 'coefficient': [1] }) @wrapper_merge_rotations def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) rx(q_machine=self.qm, params=x[:, [1]], wires=(0, )) rx(q_machine=self.qm, params=x[:, [1]], wires=(0, )) rx(q_machine=self.qm, params=x[:, [1]], wires=(0, )) rot(q_machine=self.qm, params=x, wires=(1, ), use_dagger=True) rot(q_machine=self.qm, params=x, wires=(1, ), use_dagger=True) isingxy(q_machine=self.qm, params=x[:, [2]], wires=(0, 1)) isingxy(q_machine=self.qm, params=x[:, [0]], wires=(0, 1)) cnot(q_machine=self.qm, wires=[1, 2]) ry(q_machine=self.qm, params=x[:, [1]], wires=(1, )) hadamard(q_machine=self.qm, wires=(2, )) crz(q_machine=self.qm, params=x[:, [2]], wires=(2, 0)) ry(q_machine=self.qm, params=-x[:, [1]], wires=1) return self.measure(q_machine=self.qm) input_x = tensor.QTensor([[1, 2, 3], [1, 2, 3]], dtype=pyvqnet.kfloat64) input_x.requires_grad = True qunatum_model = QModel(num_wires=3, dtype=pyvqnet.kcomplex128) qunatum_model.use_merge_rotations = True batch_y = qunatum_model(input_x) print(op_history_summary(qunatum_model.qm.op_history)) # ###################Summary####################### # qubits num: 3 # gates: {'rx': 1, 'rot': 1, 'isingxy': 2, 'cnot': 1, 'hadamard': 1, 'crz': 1} # total gates: 7 # total parameter gates: 5 # total parameters: 7 # #################################################
wrapper_compile¶
- pyvqnet.qnn.vqc.wrapper_compile(f, compile_rules=[commute_controlled_right, merge_rotations, single_qubit_ops_fuse])¶
Use compilation rules to optimize QModule’s circuits.
Note
f is the forward function of the module, and the forward function of the model needs to be run once to take effect. The model defined here inherits from pyvqnet.qnn.vqc.QModule, which is a subclass of pyvqnet.nn.Module.
- Parameters:
f – forward function.
Example:
from functools import partial from pyvqnet.qnn.vqc import op_history_summary from pyvqnet.qnn.vqc import QModule from pyvqnet import tensor from pyvqnet.qnn.vqc import QMachine, wrapper_compile from pyvqnet.qnn.vqc import pauliy from pyvqnet.qnn.vqc import QMachine, ry,rz, ControlledPhaseShift, \ rx, S, rot, isingxy,CSWAP, PauliX, T, MeasureAll, RZ, CZ, PhaseShift, u3, cnot, cry, toffoli, cy from pyvqnet.tensor import QTensor, tensor import pyvqnet class QModel_before(QModule): def __init__(self, num_wires, dtype): super(QModel_before, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.qm.set_save_op_history_flag(True) self.cswap = CSWAP(wires=(0, 2, 1)) self.cz = CZ(wires=[0, 2]) self.paulix = PauliX(wires=2) self.s = S(wires=0) self.ps = PhaseShift(has_params=True, trainable=True, wires=0, dtype=dtype) self.cps = ControlledPhaseShift(has_params=True, trainable=True, wires=(1, 0), dtype=dtype) self.t = T(wires=0) self.rz = RZ(has_params=True, wires=1, dtype=dtype) self.measure = MeasureAll(obs={ 'wires': [0], 'observables': ['z'], 'coefficient': [1] }) def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) self.cz(q_machine=self.qm) self.paulix(q_machine=self.qm) rx(q_machine=self.qm,wires=1,params = x[:,[0]]) ry(q_machine=self.qm,wires=1,params = x[:,[1]]) rz(q_machine=self.qm,wires=1,params = x[:,[2]]) rot(q_machine=self.qm, params=x[:, 0:3], wires=(1, ), use_dagger=True) rot(q_machine=self.qm, params=x[:, 1:4], wires=(1, ), use_dagger=True) isingxy(q_machine=self.qm, params=x[:, [2]], wires=(0, 1)) u3(q_machine=self.qm, params=x[:, 0:3], wires=1) self.s(q_machine=self.qm) self.cswap(q_machine=self.qm) cnot(q_machine=self.qm, wires=[0, 1]) ry(q_machine=self.qm,wires=2,params = x[:,[1]]) pauliy(q_machine=self.qm, wires=1) cry(q_machine=self.qm, params=1 / 2, wires=[0, 1]) self.ps(q_machine=self.qm) self.cps(q_machine=self.qm) ry(q_machine=self.qm,wires=2,params = x[:,[1]]) rz(q_machine=self.qm,wires=2,params = x[:,[2]]) toffoli(q_machine=self.qm, wires=[0, 1, 2]) self.t(q_machine=self.qm) cy(q_machine=self.qm, wires=(2, 1)) ry(q_machine=self.qm,wires=1,params = x[:,[1]]) self.rz(q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt class QModel(QModule): def __init__(self, num_wires, dtype): super(QModel, self).__init__() self._num_wires = num_wires self._dtype = dtype self.qm = QMachine(num_wires, dtype=dtype) self.cswap = CSWAP(wires=(0, 2, 1)) self.cz = CZ(wires=[0, 2]) self.paulix = PauliX(wires=2) self.s = S(wires=0) self.ps = PhaseShift(has_params=True, trainable=True, wires=0, dtype=dtype) self.cps = ControlledPhaseShift(has_params=True, trainable=True, wires=(1, 0), dtype=dtype) self.t = T(wires=0) self.rz = RZ(has_params=True, wires=1, dtype=dtype) self.measure = MeasureAll(obs={ 'wires': [0], 'observables': ['z'], 'coefficient': [1] }) @partial(wrapper_compile) def forward(self, x, *args, **kwargs): self.qm.reset_states(x.shape[0]) self.cz(q_machine=self.qm) self.paulix(q_machine=self.qm) rx(q_machine=self.qm,wires=1,params = x[:,[0]]) ry(q_machine=self.qm,wires=1,params = x[:,[1]]) rz(q_machine=self.qm,wires=1,params = x[:,[2]]) rot(q_machine=self.qm, params=x[:, 0:3], wires=(1, ), use_dagger=True) rot(q_machine=self.qm, params=x[:, 1:4], wires=(1, ), use_dagger=True) isingxy(q_machine=self.qm, params=x[:, [2]], wires=(0, 1)) u3(q_machine=self.qm, params=x[:, 0:3], wires=1) self.s(q_machine=self.qm) self.cswap(q_machine=self.qm) cnot(q_machine=self.qm, wires=[0, 1]) ry(q_machine=self.qm,wires=2,params = x[:,[1]]) pauliy(q_machine=self.qm, wires=1) cry(q_machine=self.qm, params=1 / 2, wires=[0, 1]) self.ps(q_machine=self.qm) self.cps(q_machine=self.qm) ry(q_machine=self.qm,wires=2,params = x[:,[1]]) rz(q_machine=self.qm,wires=2,params = x[:,[2]]) toffoli(q_machine=self.qm, wires=[0, 1, 2]) self.t(q_machine=self.qm) cy(q_machine=self.qm, wires=(2, 1)) ry(q_machine=self.qm,wires=1,params = x[:,[1]]) self.rz(q_machine=self.qm) rlt = self.measure(q_machine=self.qm) return rlt import pyvqnet import pyvqnet.tensor as tensor input_x = tensor.QTensor([[0.1, 0.2, 0.3, 0.4], [0.1, 0.2, 0.3, 0.4]], dtype=pyvqnet.kfloat64) input_x.requires_grad = True num_wires = 3 qunatum_model = QModel(num_wires=num_wires, dtype=pyvqnet.kcomplex128) qunatum_model_before = QModel_before(num_wires=num_wires, dtype=pyvqnet.kcomplex128) batch_y = qunatum_model(input_x) batch_y = qunatum_model_before(input_x) flatten_oph_names = [] print("before") print(op_history_summary(qunatum_model_before.qm.op_history)) flatten_oph_names = [] for d in qunatum_model.compiled_op_historys: if "compile" in d.keys(): oph = d["op_history"] for i in oph: n = i["name"] w = i["wires"] p = i["params"] flatten_oph_names.append({"name":n,"wires":w, "params": p}) print("after") print(op_history_summary(qunatum_model.qm.op_history)) # ###################Summary####################### # qubits num: 3 # gates: {'cz': 1, 'paulix': 1, 'rx': 1, 'ry': 4, 'rz': 3, 'rot': 2, 'isingxy': 1, 'u3': 1, 's': 1, 'cswap': 1, 'cnot': 1, 'pauliy': 1, 'cry': 1, 'phaseshift': 1, 'controlledphaseshift': 1, 'toffoli': 1, 't': 1, 'cy': 1} # total gates: 24 # total parameter gates: 15 # total parameters: 21 # ################################################# # after # ###################Summary####################### # qubits num: 3 # gates: {'cz': 1, 'rot': 7, 'isingxy': 1, 'u3': 1, 'cswap': 1, 'cnot': 1, 'cry': 1, 'controlledphaseshift': 1, 'toffoli': 1, 'cy': 1} # total gates: 16 # total parameter gates: 11 # total parameters: 27 # #################################################