quantum icon indicating copy to clipboard operation
quantum copied to clipboard

SampledExpectation layer seems to recompute the same circuits for different measurement ops

Open refraction-ray opened this issue 5 years ago • 6 comments

Example

c = cirq.Circuit()
qubits = cirq.GridQubit.rect(2, 1)
c.append(cirq.rz(0.)(qubits[0]))
c.append(cirq.H(qubits[1]))
sampled_expectation_layer = tfq.layers.SampledExpectation()
output = sampled_expectation_layer(
    [c],
    operators=[cirq.Z(qubits[0]), cirq.Z(qubits[1]), cirq.Z(qubits[0]) * cirq.Z(qubits[1])],
    repetitions=1)
print(output) # we have [1, -1, 1] sometimes
assert output[0,0]*output[0,1] == output[0,2] # and this may fail

It is unnatural to me that, when repetitions=1 (1 sample), we have inconsistent measurement results between Z1, Z2 and Z1*Z2.

And from code here https://github.com/tensorflow/quantum/blob/db2eac4e598f614a8c0e157c56313a23ef1943fb/tensorflow_quantum/core/ops/batch_util.py#L554-L561, this may be due to that each circuit, batch, measurement ops combination is simulated separately on backends. If it is so, it is not only unnatural but also inefficient since one can measure all ops for one circuit simulation.

My understanding may be wrong somewhere, any ideas on this?

refraction-ray avatar Jun 20 '20 13:06 refraction-ray

Thanks for raising this issue. I'm going to refer to the examples from the documentation here: https://www.tensorflow.org/quantum/api_docs/python/tfq/layers/SampledExpectation

bit = cirq.GridQubit(0, 0)
symbols = sympy.symbols('x y z')
ops = [cirq.Z(bit), cirq.X(bit)]
num_samples = [100, 200]
circuit = _gen_single_bit_rotation_problem(bit, symbols)
values = [[1,1,1], [2,2,2], [3,3,3]]
sampled_expectation_layer = tfq.layers.SampledExpectation()
output = sampled_expectation_layer(
    circuit,
    symbol_names=symbols,
    symbol_values=values,
    operators=ops,
    repetitions=num_samples)
# output[i][j] = The sampled expectation of ops[j] with
# values_tensor[i] placed into the symbols of the circuit
# with the order specified by feed_in_params.
# so output[1][2] = The sampled expectation of a circuit with parameter
# values [2,2,2] w.r.t Pauli X, estimated using 200 samples per term.
output  # Non-deterministic result. It can vary every time.

The output is defined as: output[i][j] = <psi(\theta_i) | OP_j | psi(\theta_i) >. In your case this means the circuit will be evaluated three different times, once with <psi | Z_0 | psi >, <psi | Z_1 | psi > , <psi | Z_0 Z_1 | psi >, where psi is made from RZ and H. Each of these outputs is estimated using only 1 sample per term.

These quantities are all simultaneously observable and can in theory all be estimated at the same time. However this is not true in all cases with more complex operators. Consider the case where each psi_i is totally different (in structure and not just parameter value) from one another and each op_j is totally different from one another. Then we have to estimate each one entirely independently of one another because they are not simultaneously observable. In order to accommodate that case and not provide ambiguous behavior (in terms of how we do sampling) between the simultaneous observable vs not simultaneous observable case, we opted to go with this behavior in order to be consistent everywhere.

The library snippet you linked actually isn't getting run in your program and is designed for use with py_functions when one needs the Cirq backend (and not the qsim backend). This is usually only the case when running through the engine or another exotic sampler interface in Cirq.

Does this clear things up ?

MichaelBroughton avatar Jun 20 '20 20:06 MichaelBroughton

@MichaelBroughton , thanks for your detailed explanation, it helps a lot! By considering non-simultaneous observables, (such as X1, Z1, X1*Z1) it is indeed better to keep the current behavior. It would be better the documentation is more clear on this point, in case someone (like me) wrongly relies on repetitions=1 and found the result a little confusing.

refraction-ray avatar Jun 21 '20 00:06 refraction-ray

Good idea! I can take that on, unless you would like to :) ?

MichaelBroughton avatar Jun 21 '20 00:06 MichaelBroughton

Please go ahead :)

refraction-ray avatar Jun 21 '20 00:06 refraction-ray

This issue has not had any activity in a month. Is it stale ?

github-actions[bot] avatar Sep 01 '20 00:09 github-actions[bot]

@MichaelBroughton Did anything more happen on this topic in later years? Should this issue be kept open, or closed?

mhucka avatar Dec 04 '24 01:12 mhucka