基于 MindQuantum 0.6.0 实现 3 量子比特幺正算符重构(涉及修改源代码)

基于 MindQuantum 实现幺正算符重构

设计设计拟设线路,使末态与目标态的保真度尽可能高。其中目标态即为由初态经过待重构的目标幺正算符操作得到。

单比特幺正算符重构演示:

比特初始到 ∣ 0 ⟩ |0\rangle ∣0 态,之后经过编码线路制备到初态,然后经过拟设线路,将初态制备到目标态,完成算符操作。此时,拟设线路就是重构出的算符。
这里编码线路为 R Z ( 0.4 ) R X ( 0.3 ) R X ( 0.2 ) RZ(0.4)RX(0.3)RX(0.2) RZ(0.4)RX(0.3)RX(0.2)。拟设用的 U3 门,目标态为 ∣ 0 ⟩ |0\rangle ∣0

# -*- coding: utf-8 -*-
"""
Created on Mon May 23 15:49:14 2022
@author: Waikikilick
"""

import numpy as np   
import mindspore as ms                         
from mindquantum import *
from mindspore import nn
from mindspore.nn import Adam, TrainOneStepCell                                 
from mindspore.common.parameter import Parameter
from mindspore.common.initializer import initializer                                   
ms.context.set_context(mode=ms.context.PYNATIVE_MODE, device_target="CPU")
ms.set_seed(1) 

class My_QLayer(nn.Cell):
    def __init__(self, expectation_with_grad, weight='normal'):
        super(My_QLayer, self).__init__()
        self.evolution = MQN2Ops(expectation_with_grad)
        weight_size = len(
            self.evolution.expectation_with_grad.ansatz_params_name)
        self.weight = Parameter(initializer(weight,
                                            weight_size,
                                            dtype=ms.float32),
                                name='ansatz_weight')

    def construct(self, x, target_state):
        return self.evolution(x, self.weight, target_state)

# encoder
encoder = Circuit()                   
encoder += H.on(0)                    
encoder += RX(f'alpha{0}').on(0)      
encoder += RY(f'alpha{1}').on(0)      
encoder += RZ(f'alpha{2}').on(0)      
encoder = encoder.no_grad() 

# ansatz
ansatz = Circuit()                           
ansatz += U3('theta','phi','lam',0)  
circuit = encoder + ansatz

alpha0, alpha1, alpha2 = 0.2, 0.3, 0.4   
encoder_data = np.array([[alpha0, alpha1, alpha2]]).astype(np.float32)
encoder_names = encoder.params_name
ansatz_names = ansatz.params_name  

ham = Hamiltonian(QubitOperator(''))     
sim = Simulator('projectq', 1)
sim_left = Simulator('projectq', 1)

grad_ops = sim.get_expectation_with_grad(ham,
                                         circuit,
                                         circ_left=Circuit(),
                                         simulator_left=sim_left,
                                         encoder_params_name=encoder_names,
                                         ansatz_params_name=ansatz_names)
QuantumNet = My_QLayer(grad_ops)
opti = Adam(QuantumNet.trainable_params(), learning_rate=0.01)     # 需要优化的是Quantumnet中可训练的参数,学习率设为0.5
net = TrainOneStepCell(QuantumNet, opti)

for i in range(500):
#     if i%100 == 0:
#         paras = list(np.squeeze(encoder_data)) + list(QuantumNet.weight.asnumpy()) 
#         paras_name = encoder_names + ansatz_names
#         pr = dict(zip(paras_name, paras))
#         state = circuit.get_qs(pr=pr)
#         fid = np.abs(np.vdot(state, np.array([1, 0])))**2           
#         print('验证保真度为:',fid)
    res = net(ms.Tensor(encoder_data),ms.Tensor(np.array([1,0])))
    if i % 10 == 0:
        print('step:',i, '训练保真度为: ', res[0,0])


paras = list(np.squeeze(encoder_data)) + list(QuantumNet.weight.asnumpy()) 
paras_name = encoder_names + ansatz_names
pr = dict(zip(paras_name, paras))
state = circuit.get_qs(pr=pr, ket=True)

print('最终量子态为\n',state)
state = circuit.get_qs(pr=pr)
fid = np.abs(np.vdot(state, np.array([1, 0])))**2           
print('最终保真度为:',fid)
ansatz_paras = list(QuantumNet.weight.asnumpy())
print('重构出来的幺正算符为:\n',ansatz.matrix(pr=dict(zip(ansatz_names, ansatz_paras))))


step: 0 训练保真度为:  0.3461229
step: 10 训练保真度为:  0.39110067
step: 20 训练保真度为:  0.4406182
step: 30 训练保真度为:  0.49330464
step: 40 训练保真度为:  0.54629815
step: 50 训练保真度为:  0.5975355
step: 60 训练保真度为:  0.64704996
step: 70 训练保真度为:  0.6942862
step: 80 训练保真度为:  0.73834836
step: 90 训练保真度为:  0.7788622
step: 100 训练保真度为:  0.81543946
step: 110 训练保真度为:  0.8479178
step: 120 训练保真度为:  0.8762677
step: 130 训练保真度为:  0.90060383
step: 140 训练保真度为:  0.9211542
step: 150 训练保真度为:  0.93823075
step: 160 训练保真度为:  0.95220006
step: 170 训练保真度为:  0.96345496
step: 180 训练保真度为:  0.97238994
step: 190 训练保真度为:  0.9793825
step: 200 训练保真度为:  0.9847798
step: 210 训练保真度为:  0.98889023
step: 220 训练保真度为:  0.99198025
step: 230 训练保真度为:  0.994274
step: 240 训练保真度为:  0.9959559
step: 250 训练保真度为:  0.9971743
step: 260 训练保真度为:  0.9980467
step: 270 训练保真度为:  0.998664
step: 280 训练保真度为:  0.9990959
step: 290 训练保真度为:  0.99939466
step: 300 训练保真度为:  0.999599
step: 310 训练保真度为:  0.99973714
step: 320 训练保真度为:  0.9998296
step: 330 训练保真度为:  0.9998907
step: 340 训练保真度为:  0.9999306
step: 350 训练保真度为:  0.9999565
step: 360 训练保真度为:  0.999973
step: 370 训练保真度为:  0.99998343
step: 380 训练保真度为:  0.9999899
step: 390 训练保真度为:  0.999994
step: 400 训练保真度为:  0.9999964
step: 410 训练保真度为:  0.9999979
step: 420 训练保真度为:  0.9999988
step: 430 训练保真度为:  0.9999993
step: 440 训练保真度为:  0.9999996
step: 450 训练保真度为:  0.99999976
step: 460 训练保真度为:  0.9999999
step: 470 训练保真度为:  0.99999994
step: 480 训练保真度为:  0.99999994
step: 490 训练保真度为:  1.0
最终量子态为
 (0.9943295181888445-0.10634283989171736j)¦0⟩
(9.78670609558259e-05-9.172955750665977e-06j)¦1⟩
最终保真度为: 0.9999999903378951
重构出来的幺正算符为:
 [[ 0.58250438+0.11411596j  0.78767193-0.16504279j]
 [-0.78767193-0.16504279j  0.58250438-0.11411596j]]

三比特幺正算符重构:

编码器为 18 参数的 3 比特线路,设计拟设线路,使末态与目标态的保真度尽可能高。其中目标态即为由初态经过待重构的目标幺正算符操作得到。
训练集包含 560 组数据,验证集包含 240 组数据。

主代码为:

# -*- coding: utf-8 -*-
"""
Created on Mon May 23 15:49:14 2022

功能:根据始末量子态,重构中间幺正操作

1. 采用卷积神经网络 
2. 对 mindquantum 源代码进行了修改,使其支持动态输入目标态

@author: Waikikilick
"""

import numpy as np   
import mindspore as ms                         
from mindquantum import *
from mindspore import nn
from mindspore.nn import Adam, TrainOneStepCell                                 
from mindspore.common.parameter import Parameter
from mindspore.common.initializer import initializer                                   
ms.context.set_context(mode=ms.context.PYNATIVE_MODE, device_target="CPU")
ms.set_seed(1) 

train_x = np.load('./new_train_x.npy', allow_pickle=True)
train_y = np.load('./new_train_y.npy', allow_pickle=True)
eval_x = np.load('./new_eval_x.npy', allow_pickle=True)
eval_y = np.load('./new_eval_y.npy', allow_pickle=True)
test_x = np.load('./test_x.npy', allow_pickle=True)

# 自定义网络层
# 本来是不支持传入 target_state 的
class My_QLayer(nn.Cell):
    def __init__(self, expectation_with_grad, weight='normal'):
        super(My_QLayer, self).__init__()
        self.evolution = MQN2Ops(expectation_with_grad)
        weight_size = len(self.evolution.expectation_with_grad.ansatz_params_name)
        self.weight = Parameter(initializer(weight,
                                            weight_size,
                                            dtype=ms.float32),
                                            name='ansatz_weight')

    def construct(self, x, target_state):
        return self.evolution(x, self.weight, target_state)

# encoder
def generate_encoder():
    enc_layer = Circuit()
    for i in range(3):
        enc_layer += U3(f'a{i}', f'b{i}', f'c{i}', i)
    coupling_layer = UN(X, [1, 2, 0], [0, 1, 2])
    encoder = Circuit()
    for i in range(2):
        encoder += add_prefix(enc_layer, f'l{i}')
        encoder += coupling_layer
    return encoder, encoder.params_name

encoder, encoder_names = generate_encoder()   
encoder.no_grad() 

# ansatz
# 卷积神经网络,卷积核为 9b
def Ansatz(layer_num=10):
    ansatz = Circuit()
    for i in range(layer_num):
        ansatz += ansatz_layer(prefix=f'layer{i}')
    return ansatz

def ansatz_layer(prefix='0'):
    _circ = Circuit()
    _circ += BarrierGate()
    _circ += conv_circ(prefix='01', bit_up=0, bit_down=1)
    _circ += BarrierGate()
    _circ += conv_circ(prefix='12', bit_up=1, bit_down=2)
    _circ += BarrierGate()
    _circ += conv_circ(prefix='20', bit_up=2, bit_down=0)
    _circ += BarrierGate()
    _circ = add_prefix(_circ, prefix)
    return _circ

def conv_circ(prefix='0', bit_up=0, bit_down=1):
    _circ = Circuit()
    _circ += U3('theta00','phi00','lam00',bit_up)
    _circ += U3('theta01','phi01','lam01',bit_down)
    _circ += X.on(bit_down,bit_up)
    _circ += RY('theta10').on(bit_up)
    _circ += RZ('theta11').on(bit_down)
    _circ += X.on(bit_up,bit_down)
    _circ += RY('theta20').on(bit_up)
    _circ += X.on(bit_down,bit_up)
    _circ += U3('theta30','phi30','lam30',bit_up)
    _circ += U3('theta31','phi31','lam31',bit_down)
    _circ = add_prefix(_circ, prefix)
    return _circ

ansatz = Circuit()                           
ansatz = Ansatz(layer_num=4)  
ansatz_names = ansatz.params_name  
circuit = encoder + ansatz
paras_name = circuit.params_name

ham = Hamiltonian(QubitOperator(''))  
sim = Simulator('projectq', 3)
sim_left = Simulator('projectq', 3)

grad_ops = sim.get_expectation_with_grad(ham,
                                         circuit,
                                         circ_left=Circuit(),
                                         simulator_left=sim_left,
                                         encoder_params_name=encoder_names,
                                         ansatz_params_name=ansatz_names)
QuantumNet = My_QLayer(grad_ops)
opti = Adam(QuantumNet.trainable_params(), learning_rate=0.001)     # 需要优化的是Quantumnet中可训练的参数,学习率设为0.5
net = TrainOneStepCell(QuantumNet, opti)

for epoch in range(10):
    print('\nepoch is:', epoch)
    
    for i in range(len(train_x)):
        encoder_data = train_x[i].reshape((1,18)).astype(np.float32)
        target_psi = train_y[i]
        res = net(ms.Tensor(encoder_data),ms.Tensor(target_psi))
        
        if i%100 == 0: # 每 100 步,用整个验证集验证一下
            print('step:', i, '训练保真度:', res[0,0])
            
            
state_list = []
for x in eval_x:
    paras = list(np.squeeze(x)) + list(QuantumNet.weight.asnumpy()) 
    pr = dict(zip(paras_name, paras))
    state = circuit.get_qs(pr=pr)
    state_list.append(state)

acc = np.real(np.mean([np.abs(np.vdot(bra, ket)) for bra, ket in zip(np.array(state_list), eval_y)]))
print('对验证集的平均保真度:', np.mean(acc))

ansatz_paras = list(QuantumNet.weight.asnumpy())
print('重构出来的幺正算符为:\n',ansatz.matrix(pr=dict(zip(ansatz_names, ansatz_paras))))

# fid_list = []
# for x, y in zip(eval_x,eval_y):
#     paras = list(np.squeeze(x)) + list(QuantumNet.weight.asnumpy()) 
#     pr = dict(zip(paras_name, paras))
#     state = circuit.get_qs(pr=pr)
#     fid = np.abs(np.vdot(state, y))**2  
#     fid_list.append(fid)
# print('验证集平均保真度:',np.mean(fid_list))

# np.save('./lala.npy',np.array(state_list))
# print('导出完成啦!')

# state_array = np.load('./lala.npy', allow_pickle=True)

# state_list = []
# for x in test_x:
#     paras = list(np.squeeze(x)) + list(QuantumNet.weight.asnumpy()) 
#     pr = dict(zip(paras_name, paras))
#     state = circuit.get_qs(pr=pr)
#     state_list.append(state)
# np.save('./heihei.npy',np.array(state_list))
# print('导出完成啦!')

epoch is: 0
step: 0 训练保真度: 0.016098816
step: 100 训练保真度: 0.31427863
step: 200 训练保真度: 0.22147878
step: 300 训练保真度: 0.14485279
step: 400 训练保真度: 0.21505353
step: 500 训练保真度: 0.38416347

epoch is: 1
step: 0 训练保真度: 0.31240866
step: 100 训练保真度: 0.50511765
step: 200 训练保真度: 0.5381597
step: 300 训练保真度: 0.7453368
step: 400 训练保真度: 0.7787936
step: 500 训练保真度: 0.8533651

epoch is: 2
step: 0 训练保真度: 0.7847961
step: 100 训练保真度: 0.8193776
step: 200 训练保真度: 0.8875419
step: 300 训练保真度: 0.9086917
step: 400 训练保真度: 0.9761023
step: 500 训练保真度: 0.9693968

epoch is: 3
step: 0 训练保真度: 0.9706415
step: 100 训练保真度: 0.97703516
step: 200 训练保真度: 0.98235166
step: 300 训练保真度: 0.9883929
step: 400 训练保真度: 0.99665827
step: 500 训练保真度: 0.9921469

epoch is: 4
step: 0 训练保真度: 0.99242043
step: 100 训练保真度: 0.99483854
step: 200 训练保真度: 0.9920595
step: 300 训练保真度: 0.9942117
step: 400 训练保真度: 0.9972964
step: 500 训练保真度: 0.9948216

epoch is: 5
step: 0 训练保真度: 0.9944427
step: 100 训练保真度: 0.996896
step: 200 训练保真度: 0.9941251
step: 300 训练保真度: 0.9954542
step: 400 训练保真度: 0.9974259
step: 500 训练保真度: 0.99540913

epoch is: 6
step: 0 训练保真度: 0.99496925
step: 100 训练保真度: 0.9975881
step: 200 训练保真度: 0.99486333
step: 300 训练保真度: 0.9959512
step: 400 训练保真度: 0.9975988
step: 500 训练保真度: 0.99554086

epoch is: 7
step: 0 训练保真度: 0.99527115
step: 100 训练保真度: 0.997855
step: 200 训练保真度: 0.995271
step: 300 训练保真度: 0.99618524
step: 400 训练保真度: 0.99788946
step: 500 训练保真度: 0.9957079

epoch is: 8
step: 0 训练保真度: 0.9958286
step: 100 训练保真度: 0.99798477
step: 200 训练保真度: 0.9958605
step: 300 训练保真度: 0.99661624
step: 400 训练保真度: 0.99830586
step: 500 训练保真度: 0.99669534

epoch is: 9
step: 0 训练保真度: 0.99712235
step: 100 训练保真度: 0.9984253
step: 200 训练保真度: 0.9973581
step: 300 训练保真度: 0.9979845
step: 400 训练保真度: 0.99896777
step: 500 训练保真度: 0.9989337
对验证集的平均保真度: 0.9994351328397008
重构出来的幺正算符为:
 [[ 7.59947141e-03+9.05753040e-03j  1.47733732e-02+1.46454241e-01j
  -1.76204151e-03+1.01860066e-03j  5.75359216e-01-1.62025345e-01j
  -3.11655701e-03+9.30582051e-04j  1.94216566e-01+1.45818288e-02j
   3.93564779e-03-2.22415661e-03j  8.99146314e-02-7.58188743e-01j]
 [ 3.26981046e-03-1.36537175e-03j  2.94734565e-02+1.58801236e-01j
   2.82942844e-03+1.94720863e-03j -4.54290350e-02+3.05537295e-02j
   2.88963622e-03-1.97000624e-03j  7.62933467e-01+5.74755663e-01j
   2.35065663e-03+4.08336465e-03j -1.64423942e-01+1.77230332e-01j]
 [-2.28597647e-02+4.42781317e-02j  1.29962227e-03-3.00651194e-03j
   1.63295972e-01+2.06087029e-02j  2.81343629e-04-1.38403944e-03j
   1.74484511e-01-1.64950519e-01j  3.39181563e-03+3.60711984e-03j
  -5.81983819e-01-7.57630232e-01j  5.19855908e-03-2.61572864e-04j]
 [ 1.67136552e-01-5.73888593e-01j -3.93497255e-03+5.51229387e-04j
   1.41878155e-01+1.62625094e-02j  8.24727060e-03+7.57564796e-03j
  -7.58000767e-01+1.00095476e-01j -1.46463874e-03+3.69237740e-03j
  -1.37838342e-02-1.93351641e-01j -1.04859476e-03+2.48670968e-03j]
 [-8.35458131e-03-5.83701897e-03j -1.03017118e-01-1.70718518e-01j
  -1.63030932e-03+7.25385939e-03j -6.26947472e-01+4.33341682e-01j
  -3.26936502e-04+6.62202099e-03j  1.40807008e-01-6.24777236e-02j
   6.03524746e-04-3.06087973e-03j -1.23543579e-01-5.83256875e-01j]
 [ 4.26501463e-03-1.45696141e-03j -8.73800324e-01+3.85797449e-01j
   8.16930617e-03-9.75368119e-04j -1.17630919e-01-2.11568785e-01j
   4.57484376e-03-2.05844832e-04j  6.69097174e-02-1.46246522e-01j
   2.13024443e-03-1.80877679e-03j  4.43002221e-02+3.30255804e-02j]
 [ 2.10867066e-01+1.17668540e-01j  1.24338767e-03-8.68227290e-03j
   3.89387785e-01-8.71912392e-01j -5.25851817e-03+3.81962849e-03j
   3.04426054e-02+4.97536905e-02j -3.98704631e-04+3.04468088e-03j
   1.50983033e-01-5.90468073e-02j -1.69310274e-03-4.36815653e-03j]
 [-4.44392299e-01+6.19808264e-01j -3.78712909e-03+2.14050266e-03j
  -1.70135126e-01-1.07595979e-01j -6.62428970e-03-7.22342468e-03j
  -5.82540411e-01-1.22143209e-01j  3.23754493e-03+7.12349754e-04j
   5.74338709e-02-1.41686926e-01j -7.00536244e-03+3.02808423e-03j]]

源代码修改

因原 MindQuantum 不支持动态传入目标量子态,需要对其源码进行一定修改。后面是在源代码中的修改内容。

1. 在 operations.py 中的修改:

class MQN2Ops(nn.Cell):
    
    def __init__(self, expectation_with_grad):
        super(MQN2Ops, self).__init__()
        _mode_check(self)
        _check_grad_ops(expectation_with_grad)
        self.expectation_with_grad = expectation_with_grad
        self.shape_ops = P.Shape()

    def extend_repr(self):
        return self.expectation_with_grad.str

    def construct(self, enc_data, ans_data, target_state): # target_state 是新加的
        check_enc_input_shape(enc_data, self.shape_ops(enc_data), len(self.expectation_with_grad.encoder_params_name))
        check_ans_input_shape(ans_data, self.shape_ops(ans_data), len(self.expectation_with_grad.ansatz_params_name))
        enc_data = enc_data.asnumpy()
        ans_data = ans_data.asnumpy()
        target_state = target_state.asnumpy() # 这行是新加的
        f, g_enc, g_ans = self.expectation_with_grad(enc_data, ans_data, target_state)
        self.f = -f   # 新加了一个负号,由梯度下降变成了梯度上升
        f = ms.Tensor(np.abs(f)**2, dtype=ms.float32)
        self.g_enc = g_enc
        self.g_ans = g_ans
        return f

    def bprop(self, enc_data, ans_data, target_state, out, dout): # 新加了 target_state
        dout = dout.asnumpy()
        enc_grad = 2 * np.real(np.einsum('smp,sm,sm->sp', self.g_enc, dout, np.conj(self.f)))
        ans_grad = 2 * np.real(np.einsum('smp,sm,sm->p', self.g_ans, dout, np.conj(self.f)))
        return ms.Tensor(enc_grad, dtype=ms.float32), ms.Tensor(ans_grad, dtype=ms.float32), ms.Tensor(np.zeros(target_state.shape), dtype=ms.float32)
        # 返回值中新加了 ms.Tensor(np.zeros(target_state.shape), dtype=ms.float32)

2. 在 simulator.py 中的修改:

def get_expectation_with_grad(self,
                                  hams,
                                  circ_right,
                                  circ_left=None,
                                  simulator_left=None,
                                  encoder_params_name=None,
                                  ansatz_params_name=None,
                                  parallel_worker=None):
        
    if isinstance(hams, Hamiltonian):
        hams = [hams]
    elif not isinstance(hams, list):
        raise TypeError(f"hams requires a Hamiltonian or a list of Hamiltonian, but get {type(hams)}")
    for h_tmp in hams:
        _check_input_type("hams's element", Hamiltonian, h_tmp)
        _check_hamiltonian_qubits_number(h_tmp, self.n_qubits)
    _check_input_type("circ_right", Circuit, circ_right)
    if circ_right.is_noise_circuit:
        raise ValueError("noise circuit not support yet.")
    non_hermitian = False
    if circ_left is not None:
        _check_input_type("circ_left", Circuit, circ_left)
        if circ_left.is_noise_circuit:
            raise ValueError("noise circuit not support yet.")
        non_hermitian = True
    if simulator_left is not None:
        _check_input_type("simulator_left", Simulator, simulator_left)
        if self.backend != simulator_left.backend:
            raise ValueError(f"simulator_left should have the same backend as this simulator, \
which is {self.backend}, but get {simulator_left.backend}")
        if self.n_qubits != simulator_left.n_qubits:
            raise ValueError(f"simulator_left should have the same n_qubits as this simulator, \
which is {self.n_qubits}, but get {simulator_left.n_qubits}")
        non_hermitian = True
    if non_hermitian and simulator_left is None:
        simulator_left = self
    if circ_left is None:
        circ_left = circ_right
    if circ_left.has_measure_gate or circ_right.has_measure_gate:
        raise ValueError("circuit for variational algorithm cannot have measure gate")
    if parallel_worker is not None:
        _check_int_type("parallel_worker", parallel_worker)
    if encoder_params_name is None and ansatz_params_name is None:
        encoder_params_name = []
        ansatz_params_name = [i for i in circ_right.params_name]
        for i in circ_left.params_name:
            if i not in ansatz_params_name:
                ansatz_params_name.append(i)
    if encoder_params_name is None:
        encoder_params_name = []
    if ansatz_params_name is None:
        ansatz_params_name = []
    _check_input_type("encoder_params_name", list, encoder_params_name)
    _check_input_type("ansatz_params_name", list, ansatz_params_name)
    for i in encoder_params_name:
        _check_input_type("Element of encoder_params_name", str, i)
    for i in ansatz_params_name:
        _check_input_type("Element of ansatz_params_name", str, i)
    s1 = set(circ_right.params_name) | set(circ_left.params_name)
    s2 = set(encoder_params_name) | set(ansatz_params_name)
    if s1 - s2 or s2 - s1:
        raise ValueError("encoder_params_name and ansatz_params_name are different with circuit parameters")
    circ_n_qubits = max(circ_left.n_qubits, circ_right.n_qubits)
    if self.n_qubits < circ_n_qubits:
        raise ValueError(f"Simulator has {self.n_qubits} qubits, but circuit has {circ_n_qubits} qubits.")
    version = "both"
    if not ansatz_params_name:
        version = "encoder"
    if not encoder_params_name:
        version = "ansatz"

    def grad_ops(*inputs):
        if version == "both" and len(inputs) != 3: # 因需要多输入一个目标量子态,由原来的 !=2 变成了 != 3.
            raise ValueError("Need two inputs!")
        if version in ("encoder", "ansatz") and len(inputs) != 1:
            raise ValueError("Need one input!")
        if version == "both":
            _check_encoder(inputs[0], len(encoder_params_name))
            _check_ansatz(inputs[1], len(ansatz_params_name))
            batch_threads, mea_threads = _thread_balance(inputs[0].shape[0], len(hams), parallel_worker)
            inputs0 = inputs[0]
            inputs1 = inputs[1]
            target_state = inputs[2] # 多加了这一行
        if version == "encoder":
            _check_encoder(inputs[0], len(encoder_params_name))
            batch_threads, mea_threads = _thread_balance(inputs[0].shape[0], len(hams), parallel_worker)
            inputs0 = inputs[0]
            inputs1 = np.array([])
        if version == "ansatz":
            _check_ansatz(inputs[0], len(ansatz_params_name))
            batch_threads, mea_threads = _thread_balance(1, len(hams), parallel_worker)
            inputs0 = np.array([[]])
            inputs1 = inputs[0]
        if non_hermitian:
            simulator_left.sim.set_qs(target_state) # 多加了这一行
            f_g1_g2 = self.sim.non_hermitian_measure_with_grad([i.get_cpp_obj() for i in hams],
                                                               [i.get_cpp_obj(hermitian=True) for i in hams],
                                                               circ_left.get_cpp_obj(),
                                                               circ_left.get_cpp_obj(hermitian=True),
                                                               circ_right.get_cpp_obj(),
                                                               circ_right.get_cpp_obj(hermitian=True), inputs0,
                                                               inputs1, encoder_params_name, ansatz_params_name,
                                                               batch_threads, mea_threads, simulator_left.sim)
        else:
            f_g1_g2 = self.sim.hermitian_measure_with_grad([i.get_cpp_obj()
                                                            for i in hams], circ_right.get_cpp_obj(),
                                                           circ_right.get_cpp_obj(hermitian=True), inputs0, inputs1,
                                                           encoder_params_name, ansatz_params_name, batch_threads,
                                                           mea_threads)
        res = np.array(f_g1_g2)
        if version == 'both':
            f = res[:, :, 0]
            g1 = res[:, :, 1:1 + len(encoder_params_name)]
            g2 = res[:, :, 1 + len(encoder_params_name):]
            return f, g1, g2
        f = res[:, :, 0]
        g = res[:, :, 1:]
        return f, g

    grad_wrapper = GradOpsWrapper(grad_ops, hams, circ_right, circ_left, encoder_params_name, ansatz_params_name,
                                  parallel_worker)
    s = f'{self.n_qubits} qubit' + ('' if self.n_qubits == 1 else 's')
    s += f' {self.backend} VQA Operator'
    grad_wrapper.set_str(s)
    return grad_wrapper
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值