Git Product home page Git Product logo

Comments (10)

1ucian0 avatar 1ucian0 commented on June 10, 2024

Are switch statements supported on the backend? It is not listed in the feature table.

Maybe that's the problem? I'm moving this to qiskit-ibm-runtime. Consider updating to 0.46/1.0 and extend on your example.

from qiskit.

prakharb10 avatar prakharb10 commented on June 10, 2024

Hi @1ucian0
I'm unsure if the runtime repo is the right place for this since, on the surface, the trouble looks like a part of qiskit.

Maybe that's the problem?

I did try replacing the switch statement with if, but the issue persists.

Consider updating to 0.46/1.0 and extend on your example.

The issue is present in Qiskit 1.0

Also, the issue happens with both qiskit-ibm-provider and qiskit-ibm-runtime (which doesn't support transpiling dynamic circuits out of the box - Qiskit/qiskit-ibm-runtime#1253).

from qiskit.

prakharb10 avatar prakharb10 commented on June 10, 2024

Patrick, from the IBM Quantum Support Team, shared the following concise code snippets, which raise the same error:

qr = QuantumRegister(4, "q")
cr = ClassicalRegister(3, "cr")
qc = QuantumCircuit(qr, cr)

with qc.if_test((cr[1], 1)) as _else:
    qc.x(0, label="X1111i").c_if(cr, 4)
with _else:
   qr1 = QuantumRegister(2, "qr1")
   cr1 = ClassicalRegister(2, "cr1")
   inst = QuantumCircuit(2, 2, name='t').to_instruction()
   qc.append(inst, [qr[0], qr[1]], [cr[0], cr[1]])
# qc.draw('mpl') 
qc.draw(style={"showindex": True})
from qiskit.circuit import QuantumCircuit, Qubit, Clbit
q_bits = [Qubit(), Qubit(), Qubit()]
c_bits = ClassicalRegister(2,'cr')
qc = QuantumCircuit(q_bits, c_bits)

with qc.if_test((c_bits[1], 0)) as else_:
qc.x(0, label="pat").c_if(c_bits, 4)
with else_:
inst = QuantumCircuit(1, 1, name='t').to_instruction()
qc.append(inst, [0],[1])

from qiskit.

1ucian0 avatar 1ucian0 commented on June 10, 2024

I had to readjust the snippets, but they both worked when I ran them on qiskit 1.0.1 and qiskit 0.46.0:

from qiskit.circuit import QuantumCircuit, ClassicalRegister, QuantumRegister

q_bits = QuantumRegister(2, 'qr')
c_bits = ClassicalRegister(2,'cr')
qc = QuantumCircuit(q_bits, c_bits)

with qc.if_test((c_bits[1], 0)) as else_:
    qc.x(0, label="pat").c_if(c_bits, 4)
with else_:
    inst = QuantumCircuit(1, 1, name='t').to_instruction()
qc.append(inst, [0],[1])
from qiskit.circuit import QuantumCircuit, ClassicalRegister, QuantumRegister

qr = QuantumRegister(4, "q")
cr = ClassicalRegister(3, "cr")
qc = QuantumCircuit(qr, cr)

with qc.if_test((cr[1], 1)) as _else:
    qc.x(0, label="X1111i").c_if(cr, 4)
with _else:
   qr1 = QuantumRegister(2, "qr1")
   cr1 = ClassicalRegister(2, "cr1")
   inst = QuantumCircuit(2, 2, name='t').to_instruction()
   qc.append(inst, [qr[0], qr[1]], [cr[0], cr[1]])
qc.draw(style={"showindex": True})   # or qc.draw('mpl')

from qiskit.

prakharb10 avatar prakharb10 commented on June 10, 2024

but they both worked when I ran them on qiskit 1.0.1 and qiskit 0.46.0

Could you clarify if by "running" you mean the circuit builds or that it runs on the hardware? The former always worked, and the latter is where the issue pops up.

from qiskit.

jakelishman avatar jakelishman commented on June 10, 2024

@prakharb10: apologies for the slow reply from us. It's no excuse, this issue just happened to come in right in the middle of the Qiskit 1.0 final release push, and I think it got missed.

I can reproduce your issue when running on our hardware with this most minimal reproducer:

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

qr = QuantumRegister(27, "q")
cr = ClassicalRegister(3, "cr")
qc = QuantumCircuit(qr, cr)

with qc.if_test((cr[1], 1)):
    with qc.if_test((cr, 4)):
        qc.x(0)

That said, I got that reproducer from one of our internal support team, not from your QPY file, and then minimised it myself, so it might not be exactly the same problem you're seeing.

With my minimal reproducer, the problem seems to enter the circuit in our internal code that prepares the circuits to run. That said, I think the actual root cause might be the "nested" issue I was foreseeing in this comment on Qiskit #10108 (comment) rearing its head (but I'm not certain).

In your QPY file, it looks like you're using a lot of nested classical instructions that act on classical data, with a lot of nested conditionals that act on registers, so the second part of that definitely appears to be an effect of what I mentioned in #10108 (comment), which is triggered by our internal code.

We're looking into how we reach that error state internally, but for right now, the status is that nested control-flow with register conditions will fail with this error.

It will look very ugly, but as a very temporary workaround, if you can write your conditions in terms of bitwise expressions, you might be able to get something working successfully. Looking at your QPY file, that might be quite tricky (and certainly I don't love that I need to make this suggestion), but here I've written a function that converts conditions on registers to bitwise conditions. If you replace all (register, value) tuples in your if_test calls with condition_to_expr(register, value), I think you should get something working:

from qiskit.circuit.classical import expr

def condition_to_expr(reg, value):
    def bit_compare(bit, value):
        return expr.lift(bit) if value else expr.logic_not(bit)

    new_condition = bit_compare(reg[0], value & 1)
    value >>= 1
    for bit in reg[1:]:
        new_condition = expr.logic_and(new_condition, bit_compare(bit, value & 1))
        value >>= 1
    return new_condition

So as an example, I modified my example above to this:

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

qr = QuantumRegister(27, "q")
cr = ClassicalRegister(3, "cr")
qc = QuantumCircuit(qr, cr)

with qc.if_test(condition_to_expr(cr, 1)):
    with qc.if_test(condition_to_expr(cr, 4)):
        qc.x(0)

and that executed successfully on hardware.

from qiskit.

jakelishman avatar jakelishman commented on June 10, 2024

Luciano: can you transfer this back to Qiskit for now, because at a minimum I think there's issues we need to solve on our side, and there's a separate tracking issue on the internal code base as well. (I don't have write on this repo, so can't transfer it back.)

(edit: I also just noticed that you're using the base of the same reproducer I was haha.)

from qiskit.

prakharb10 avatar prakharb10 commented on June 10, 2024

Thank you for highlighting the root cause, @jakelishman. The fact that you could foresee this brings a degree of comfort, in some sense.

The workaround will undoubtedly help when running shallow circuits with nested control-flow instructions. For now, I will hold off on using it for the initial dense circuit. I'm already doing a "bit shift" for the current circuit in parts where I only want to condition on a subset of the classical register, e.g., bits 2-4. I ran into another error when using conditionals on multiple classical registers (details in the footer of the original comment).

I don't know if you already have an agreed design for tackling this, but please let me know if I can help with the implementation or any other way.

from qiskit.

jakelishman avatar jakelishman commented on June 10, 2024

Oh, I missed those comments at the bottom, sorry. In general, you can't wrap up conditions on registers into an Instruction (which is what happens if you try to QuantumCircuit.append with a QuantumCircuit argument); the Instruction data model is not designed to close over classical registers at all, so any places where it works are unexpected (and I'd take care with).

switch is supported on all IBM backends that support if. The IBM hardware requires (or at least used to require) a default branch in the switch statement, whether or not it was reachable, in case you're running into problems.

from qiskit.

prakharb10 avatar prakharb10 commented on June 10, 2024

(which is what happens if you try to QuantumCircuit.append with a QuantumCircuit argument)

I ran into dissonating behavior between QuantumCircuit.append and QuantumCircuit.compose. Is there a particular scenario when either should be used? I ended up using QuantumCircuit.compose (with inplace=True) throughout.

In general, you can't wrap up conditions on registers into an Instruction

Is that what happens when you try to run such a circuit (one with conditionals on multiple classical registers) on the simulator - the circuit is converted to an instruction?

My methodology was to build parts of the circuit piecewise and then compose them together. I'm wondering if I need to switch to building a single circuit at the start and imperatively add operations to it.

The IBM hardware requires (or at least used to require) a default branch in the switch statement, whether or not it was reachable, in case you're running into problems.

The issue with the nested control-flow instructions is the only message I saw. My initial concern was to check if errors with switch statements might be bubbling up as the context error message. I do not think that is the case after your explanation.

from qiskit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.