tensorflow/quantum

problem about Paramsolver in cirq and in QTF

LeeQY1996 opened this issue · 2 comments

I have a problem about Paramsolver in cirq and in QTF. I construct a hardware efficient circuit to do VQE algorithm. I use QTF to generate a tf.keras.models.Model and optimize this circuit to get optimal parameter values and estimation energy value . I use three methods to test this parameter values. Firstly, I use set_weights to set optimal parameters to this QTF.model and get the estimation value. The two way get the same value. And I use other two methods, tfq.layers.Expectation() and simulator.simulate_expectation_values() to do the same calculation. But I find that the same optimal parameters and the same circuit, I get different estimation values. The QFT.model and set_weights are the same values. And tfq.layers.Expectation() and simulator.simulate_expectation_values() are the same values. But if the circuit only contains 8 parameters or less, The four methods get the same values.
parameters_number:8, QTF_value:-0.4172770082950592, Reset_Weights_QTF_Value:[[-0.417277]], QTF.Expectation_value:[[-0.417277]], Simulator_value:[(-0.4172773063182831+0j)]

parameters_number:16, QTF_value:-4.257663726806641, Reset_Weights_QTF_Value:[[-4.2576637]], QTF.Expectation_value:[[-1.1815777]], Simulator_value:[(-1.1815786734223366+7.450580596923828e-09j)]

My code is available here

That's because the internal ordering of the PQC is different. I.e. if we compare the PQC layer's ._symbols with the params_str we can see the difference. ._symbols = tf.Tensor( [b'vqe0' b'vqe1' b'vqe10' b'vqe11' b'vqe12' b'vqe13' b'vqe14' b'vqe15' b'vqe2' b'vqe3' b'vqe4' b'vqe5' b'vqe6' b'vqe7' b'vqe8' b'vqe9'], shape=(16,), dtype=string) where as params_str = tf.Tensor( [b'vqe0' b'vqe1' b'vqe2' b'vqe3' b'vqe4' b'vqe5' b'vqe6' b'vqe7' b'vqe8' b'vqe9' b'vqe10' b'vqe11' b'vqe12' b'vqe13' b'vqe14' b'vqe15'], shape=(16,), dtype=string). Hence when you are getting the weights (which are in the order of the PQC's, so it would be weight_0 weight_1 weight_10) and trying to plug them into a different ordering, you get different results.

If you want to keep this approach (and use expectation layers with pretrained weights) you can use the logic that the PQC uses to get the ordering:

self._symbols_list = list(
           sorted(util.get_circuit_symbols(model_circuit)))
self._symbols = tf.constant([str(x) for x in self._symbols_list])

I.e. you can get the exact outputs by simply doing the following at the end of the code:

# These are the only two lines that are different
params_str = list(sorted(tfq.util.get_circuit_symbols(circuit))) 
params = [sympy.symbols(i) for i in params_str] 

qev=tfq.layers.Expectation()(circuit,
                         symbol_names=params_str,
                         symbol_values=[theta],
                         operators=observable)


#using simulator to get the estimation energy value.
simulator=Simulator()
resolver=Param(theta,params) #参数器 
sv=simulator.simulate_expectation_values(circuit,observable,resolver)

And this will yield and output of: parameters_number:16, QTF_value:-4.212678909301758, Reset_Weights_QTF_Value:[[-4.212679]], QTF.Expectation_value:[[-4.212679]], Simulator_value:[(-4.212678354233503+0j)]

Thank you very much for helping me solve this very important problem.