qiskit-ignis icon indicating copy to clipboard operation
qiskit-ignis copied to clipboard

Hamiltonian Tomography with Pulse

Open dcmckayibm opened this issue 6 years ago • 10 comments

What is the expected behavior?

dcmckayibm avatar Sep 23 '19 21:09 dcmckayibm

We should extend tomography module for QuantumCircuit already existing in qiskit-ignis/qiskit/ignis/verification/tomography. When QuantumCircuit is given, the tomography module adds state preparation circuits and measurement circuits to the given circuit, then the module returns a list of QuantumCircuits for combination of all given bases.

https://github.com/Qiskit/qiskit-ignis/blob/b65da6186f1181954207e1b849fa0208bf23fb75/qiskit/ignis/verification/tomography/basis/circuits.py#L342-L351

The problem of giving a pulse Schedule instead of QuantumCircuit is that those objects have no common interface, and they cannot be added each other. We have several options to avoid this issue.

1. Including scheduler within tomography module

This is the simplest way of avoiding schedule+circuit issue. When a Schedule object is given as a function input, state preparation circuit and measurement circuit are internally converted into Schedule and added to the given Schedule.

Pros:

  • Simplest implementation.

Cons:

  • All functions in the tomography module even public one have name *_circuit. I guess this naming rule is to differentiate tomography module for circuit from one for pulse, but actual implementation will be identical except for circuit->pulse conversion part. Adding separate *_pulse functions is just redundant, but we cannot rename the functions because some of them are already public.
  • We need to modify interface of tomography module, because the scheduler requires CmdDef. This means the output of tomography function becomes dedicated to some backend, while output at circuit-level is universal for all backends. This might be weird.

2. Preparing pseudo QuantumCircuit for pulse experiments

In this implementation, a pulse experiment is represented by QuantumCircuit. In this case, what the tomography module receives is always a circuit, and we don't need to change the module itself.

Pros:

  • We don't need to change the tomography module.
  • The module becomes common for pulse/circuit experiments.

Cons:

  • To fully parametrize pulse instruction, we should deploy analytic pulse. User might be able to create parametrized QuantumCircuit at pulse-level with CmdDef consisting of ParametrizedSchedules of analytic pulses, but analytic pulse is not available now. Of course pulse scheduler doesn't support this procedure. We need major refactoring of pulse module in terra.
  • Maybe we can define something like PulseCircuit class which inherit from QuantumCircuit and have schedule object internally (what scheduler really needs is schedule and qubits), but this complicates terra.

3. Creating metaclass for QuantumCircuit and Schedule

In this implementation, QuantumCircuit and Schedule are unified as, let's say, QuantumInstruction. Of course they can be added. Scheduler takes a set of QuantumInstruction and convert everything into Schedule. - I'm not sure if it make sense.

Pros:

  • Users may want to replace a part of QuantumCircuit by their custom Schedule, and having this data structure enables this kind of operation natively.

Cons:

  • This is infeasible in short term.

nkanazawa1989 avatar Oct 01 '19 12:10 nkanazawa1989

Implementing 2. will require promoting a pulse schedule to a circuit. This will require fixing the later transpilation based off of this so as not to force assigning schedule to correct qubits. This has always been a planned feature. I will bring it up at the internal meeting this morning.

taalexander avatar Oct 01 '19 13:10 taalexander

I think 2 is best because we also want to avoid having the scheduler code in too many places and/or make the schedule code too complicated.

In the short term 2 can be done with hard coded pulses (it will add a lot of pulses to the pulse library if there are a lot of variations, e.g., like the rabi). In the longer term I agree there should be some type of analytic pass around. The problem is that it needs to get synced to whatever is being considered for parameterized pulses on the backend otherwise it's not useful.

dcmckayibm avatar Oct 01 '19 14:10 dcmckayibm

seems to be better to adopt 2.

Do we have a plan to provide a pass to revert schedule to circuit? It sounds like the best option to use here. However, for example, a schedule of Rabi pulse with intermediate amps doesn't have an exact gate definition, and it will generate bunch of CmdDefs for each amp. To avoid this, pulse schedule to circuit module should be analytic pulse based.

Anyways hard coded pulse seems to be the most feasible solution for now.

https://github.com/Qiskit/qiskit-terra/blob/a0290821af49bd5ee8269ae07831ecad77d4cfe8/qiskit/scheduler/methods/basic.py#L175-L177

In this case, pulse scheduler requires only gate instruction name and qubits (no params since it is hard coded). We can create helper function to create (e.g. Rabi) Schedule + qubits (dict[channel: qubit]) -> fake gate Instruction (it has only name of original schedule) + (CmdDef) Schedule. Then it creates pseudo QuantumCircuit with the fake gate and adds schedule by CmdDef.add(). Tomography module can take this pseudo QuantumCircuit as an input, then scheduler reconstruct original pulse schedule with extended state prep/meas circuits.

The helper function has no dependency on Ignis. I think this should be a PR for Terra. I'll make another PR for the fitter of Hamiltonian tomography. This goes to Ignis.

nkanazawa1989 avatar Oct 01 '19 16:10 nkanazawa1989

I noticed an example in which 2 doesn’t work.

In the case of QPT in Pauli basis, scheduler will generate following schedule.

——[prep A]——[circ]——(barrier)——[proj B]——[acquire]——
t0        t1      t2         t3        t4         t5

Exp1: (A,B) = (Zp, Z)

  • prep Zp duration 0
  • circ duration 100
  • proj Z duration 0

Exp2: (A,B) = (Xp, X)

  • prep Xp duration 10
  • circ duration 100
  • proj X duration 10

What we want to generate for Exp1 and Exp2 is schedule having the same t2-t4 interval to avoid error from coherence.

(After scheduler)

  • Exp1: t1=0, t2, t4=100
  • Exp2: t1=10, t2=110, t4=120

This is why rescheduler is used, but this just aligns t4 time of experiments. If we align t4 of Exp1 and Exp2, rescheduler gives inconsistent t2-t4 interval.

(After reschedule)

  • Exp1: t1=0, t2=100, t4=120
  • Exp2: t1=10, t2=110, t4=120

Exp1 starts acquisition 20dt after circ, but Exp2 starts 10dt after circ.

The only way solving this is to implement 1. In this case, scheduler is in tomography module and we can explicitly specify all timing in above example - we can align t1 as well.

  • Exp1: t1=10, t2=110, t4=120

nkanazawa1989 avatar Oct 08 '19 13:10 nkanazawa1989

Have you thought about a scheduling pass? It would function over a list of schedules, applying basic "as-late-as-possible" pass to each schedule, but shifting the group of schedules (or prepending with a delay) so that they end at the time of the longest schedule. Would be minimal code and no API changes. (I am assuming that the workflow would be that a user gets the circuit from ignis, defines custom pulses for a backend, then schedules the circuit for the backend.) Would that work for this?

lcapelluto avatar Oct 08 '19 14:10 lcapelluto

Yes, I did. If I understand correctly, scheduler works for list of circuits, but they are independently processed. https://github.com/Qiskit/qiskit-terra/blob/a0290821af49bd5ee8269ae07831ecad77d4cfe8/qiskit/compiler/schedule.py#L64

Maybe this can be modified so that alap pass functions for list of schedules, but there is another issue. As you mentioned, Ignis gives a list of QPT circuits and we covert it into schedule with custom CmdDef (Ignis prepares different initial states and run given circuit, then it measures final state in different basis - it returns multiple circuits for single circuit input). Each QPT circuit comprises three blocks, namely, state preparation, given circuit, and projection+measurement. However, this context is lost in QPT circuits because all blocks are integrated to be a single circuit, and scheduler doesn’t find boundary of circuit and projection. What we need to do is extract maximum duration taken by projection among list of QPT circuits, and need to shift measurement so that the interval of time when we get a final state (t2) and time starting acquisition (t4) becomes identical over all QPT circuits - pulse duration of projection is usually basis dependent. Identical t2-t4 interval ensures this.

However, in Pauli basis case, maximum duration of projection part is up to 10-30dt in recent devices (just tens of ns), and decay of state during the time could be ignored. In this case, we don't need to take care about above problem. @dcmckayibm ?

Of course I prefer minimal code change, and if there is any workaround, I’m very happy.

nkanazawa1989 avatar Oct 09 '19 01:10 nkanazawa1989

The problem you're describing can even be present in Qasm QPT (not involving pulse at all). I would say if you restrict all singles to be defined only in terms of U3 it solves the problem.

With the introduction of scheduling, you may think of a barrier that persists across experiments in the same job, but I would push that discussion somewhere else.

For now I would do just as @lcapelluto suggests.

dcmckayibm avatar Oct 09 '19 02:10 dcmckayibm

Yes. It is also problem in Qasm QPT. Replacing projection circuit by U3 is good direction. But if this problem doesn't degrade QPT result, based on your experience, I'll just ignore the effect of inconsistent projection duration.

From the viewpoint of scheduling, barrier persists across experiment is also good solution. To have multiple such barrier in a job, maybe it is better to have label for each barrier, and the scheduler aligns the position of the barrier of the same label, and of course avoid optimization across the barrier.

nkanazawa1989 avatar Oct 09 '19 02:10 nkanazawa1989

FYI Issue #283 is somewhat related. I think the issue in #283 is that pulse experiments always return counts over all qubits, not just the ones that we actually care about measuring (which is never really surfaced to the pulse schedule). Think a marginalize_counts call is needed.

singular-value avatar Oct 22 '19 19:10 singular-value