1

I need to calculate the expectation values of an operator h for various quantum states ψ on an IBMQ quantum machine. This can be done using the method described in this answer like the following,

 for i, inp in enumerate(x):
     parameters = {list(a.parameters)[0]: inp}
     ψ = CircuitStateFn(a.assign_parameters(parameters))
     measurable_expression = StateFn(h, is_measurement=True).compose(ψ)   
     expectation = PauliExpectation().convert(measurable_expression)
     sampler = CircuitSampler(qi).convert(expectation)
     y[i] = sampler.eval().real 
     z[i] = sampler.eval().imag

Now, I've noticed that these jobs sits idle in the queue for a long time before being executed which itself doesn't take too long. So I am thinking of submitting multiple jobs in parallel. I thought of providing a ThreadPoolExecutor to the backend but it seems that it only works with AerSimulator not real quantum hardware.

Is there a way to do this? Thanks.

bisarch
  • 189
  • 1
  • 7

1 Answers1

1

You can add all the measurement expressions in one list operator. This way, all the circuits needed to be executed will be sent to the backend at once as a single job:

from qiskit.opflow.list_ops import ListOp

measurable_expressions_list = [] for i, inp in enumerate(x): parameters = {list(a.parameters)[0]: inp} ψ = CircuitStateFn(a.assign_parameters(parameters)) measurable_expression = StateFn(h, is_measurement=True).compose(ψ) measurable_expressions_list.append(measurable_expression)

expect_ops = PauliExpectation().convert(ListOp(measurable_expressions_list)) sampler = CircuitSampler(quantum_instance) sampled_ops = sampler.convert(expect_ops) expectation_values = sampled_ops.eval()

for i, exp_val in enumerate(expectation_values): y[i] = exp_val.real z[i] = exp_val.imag

print(y, z)

Egretta.Thula
  • 9,972
  • 1
  • 11
  • 30
  • Does this split your circuits into multiple jobs, submit them, and consolidate the results if the number of circuits exceed the maximum allowed for a backend per job like IBMQJobManager.run does? https://quantumcomputing.stackexchange.com/a/12758 – bisarch Oct 10 '22 at 12:16
  • 1
    Yes! This happens in run_circuits() function which is used by QuantumInstance class. – Egretta.Thula Oct 11 '22 at 03:44
  • Is it possible to map the virtual qubits to particular physical qubits (something that I can do if I have access to the circuit) in the method above? For example https://quantumcomputing.stackexchange.com/questions/17736/how-can-i-specify-the-qubits-on-quantum-computers-that-i-want-to-use – bisarch Oct 11 '22 at 14:33
  • 1
    Note that, CircuitSampler takes an instance of QuantumInstance as a parameter (qi in your code snippet). Which means you can use the exact same idea. – Egretta.Thula Oct 11 '22 at 16:41
  • I specifically want to use NoiseAdaptiveLayout. Do you think this will do the trick? noise_adaptive_layout = NoiseAdaptiveLayout(backend.properties()) pass_manager = PassManager() pass_manager.append(noise_adaptive_layout) qi = QuantumInstance(backend, pass_manager=pass_manager, seed_transpiler=seed, seed_simulator=seed, noise_model=noise_model) – bisarch Oct 11 '22 at 17:01
  • That leads to the error Error is : The Qobj uses gates (['h', 'sdg', 'rx']) that are not among the basis gates (['id', 'rz', 'sx', 'x', 'cx', 'reset']). Error code: 1106.. Re-submit the circuits. – bisarch Oct 11 '22 at 17:34
  • 1
    Instead of creating a new pass manager and struggling with its configuration, you can use one of the preset pass managers and change its layout_method: pmc = PassManagerConfig.from_backend(backend) pmc.layout_method = 'noise_adaptive' pass_manager = level_2_pass_manager(pmc) – Egretta.Thula Oct 12 '22 at 06:53
  • Thanks. Any specific reason why you have level_2_pass_manager there instead of say level_3_pass_manager? I tried using the later in the above code which leads to TypeError: TwoQubitWeylDecomposition.__new__() missing 1 required positional argument: 'unitary_matrix' – bisarch Oct 12 '22 at 14:42