1
$\begingroup$

I have a 2 qubit (+1 ancillary qubit) circuit in Qiskit which calculates the classical OR gate (q0 or q1) as follows:

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer

for input in ['00','01','10','11']:
    
    mycircuit1 = QuantumCircuit(3,1)
    
    #Initialization - Note qiskit order
    if input[0] == '1':
        mycircuit1.x(1)
    if input[1] == '1':
        mycircuit1.x(0)

    mycircuit1.cx(0,2)
    mycircuit1.cx(1,2)
    mycircuit1.ccx(0,1,2)

    mycircuit1.measure(2,0)

    job    = execute(mycircuit1, Aer.get_backend('qasm_simulator'), shots = 1000)
    counts = job.result().get_counts(mycircuit1)
    print("Input:", input, "Output:", counts)

that returns:

Input: 00 Output: {'0': 1000}
Input: 01 Output: {'1': 1000}
Input: 10 Output: {'1': 1000}
Input: 11 Output: {'1': 1000}

and and I want to expand it to a 3 qubit(+1 ancillary qubit) circuit that calculates (q0 or q1 or q2) but I do not know how. One way of thinking is that (q0 OR q1 OR q2) = (qo OR q1) OR q2 so I can put the gates from the previous circuit and repeat the process. However, I do not know how to bind these two together. Here is the circuit that I have at the moment:

from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer

for input in ['000','100','010','001', '110','011','101','111']:
    
    mycircuit1 = QuantumCircuit(4,1)
    
    #Initialization - Note qiskit order
    if input[0] == '1':
        mycircuit1.x(1)
    if input[1] == '1':
        mycircuit1.x(0)

    mycircuit1.cx(0,2)
    mycircuit1.cx(1,2)
    mycircuit1.ccx(0,1,2)

    mycircuit1.barrier()

    mycircuit1.cx(1,3)
    mycircuit1.cx(2,3)
    mycircuit1.ccx(1,2,3)
    
    mycircuit1.measure(3,0)

    job    = execute(mycircuit1, Aer.get_backend('qasm_simulator'), shots = 1000)
    counts = job.result().get_counts(mycircuit1)
    print("Input:", input, "Output:", counts)

that returns:

Input: 000 Output: {'0': 1000}
Input: 100 Output: {'1': 1000}
Input: 010 Output: {'1': 1000}
Input: 001 Output: {'0': 1000}
Input: 110 Output: {'1': 1000}
Input: 011 Output: {'1': 1000}
Input: 101 Output: {'1': 1000}
Input: 111 Output: {'1': 1000}

I am stuck at this point and I do not know what to do next. As demonstrated in the results if q0 or q1 equals one, the final result would be one, so if I can fix the problem in the 001 input, I can say I implemented the classical OR gate for three inputs.

$\endgroup$
1
  • $\begingroup$ Have you looked at qiskit's append method for quantum circuits. You can append a whole circuit, specifying which qubits you're applying it to. $\endgroup$
    – DaftWullie
    Commented May 4, 2023 at 8:27

2 Answers 2

3
$\begingroup$

There are two errors in your code:

  1. You only initialize the first two bits, the last bit of the input is unused. Thus, you should replace:
    if input[0] == '1':
        mycircuit1.x(1)
    if input[1] == '1':
        mycircuit1.x(0)

by (I've also replaced input by input_ because input is a built-in):

    for index, bit in enumerate(input_[::-1]):
        if bit == '1':
            mycircuit1.x(index)
  1. You have to use 5 qubits in total, not 4: 3 to store the input bits, 1 to store q0 or q1 and 1 to store (q0 or q1) or q2.

Thus, your code should look like this:

for input_ in ['000','100','010','001', '110','011','101','111']:
    mycircuit1 = QuantumCircuit(5,1)
    
    # Reverse input_ because of qiskit order
    for index, bit in enumerate(input_[::-1]):
        if bit == '1':
            mycircuit1.x(index)

    mycircuit1.cx(0, 3)
    mycircuit1.cx(1, 3)
    mycircuit1.ccx(0, 1, 3)

    mycircuit1.barrier()

    mycircuit1.cx(2, 4)
    mycircuit1.cx(3, 4)
    mycircuit1.ccx(2, 3, 4)
    
    mycircuit1.measure(4,0)

    job    = execute(mycircuit1, Aer.get_backend('qasm_simulator'), shots = 1000)
    counts = job.result().get_counts(mycircuit1)
    print("Input:", input_, "Output:", counts)

Note however that, as mentioned by DaftWullie in the comments, you can define a QuantumCircuit that you want to append to your main circuit. For instance, define:

or_circ = QuantumCircuit(3)
or_circ.cx(0, 2)
or_circ.cx(1, 2)
or_circ.ccx(0, 1, 2)

And you can then do:

for input_ in ['000','100','010','001', '110','011','101','111']:
    mycircuit1 = QuantumCircuit(5,1)
    
    # Reverse input_ because of qiskit order
    for index, bit in enumerate(input_[::-1]):
        if bit == '1':
            mycircuit1.x(index)

    mycircuit1.append(or_circ, [0, 1, 3])

    mycircuit1.barrier()

    mycircuit1.append(or_circ, [2, 3, 4])
    
    mycircuit1.measure(4,0)

    job    = execute(mycircuit1, Aer.get_backend('qasm_simulator'), shots = 1000)
    counts = job.result().get_counts(mycircuit1)
    print("Input:", input_, "Output:", counts)

As a final note, since you know that q0 OR q1 is equivalent to NOT (NOT q0 AND NOT q1), you can define your OR gate with only X and CCX gates:

or_circ = QuantumCircuit(3)
or_circ.x([0, 1, 2])
or_circ.ccx(0, 1, 2)
or_circ.x([0, 1])

Using this gate would still give you the right results.


Finally, note that you can use the same last trick to implement the OR gate with only 4 qubits: just use an MCX gate, which represents the logical AND and negate it:

for input_ in ['000','100','010','001', '110','011','101','111']:
    mycircuit1 = QuantumCircuit(4, 1)
    
    # Reverse input_ because of qiskit order
    for index, bit in enumerate(input_[::-1]):
        if bit == '1':
            mycircuit1.x(index)

    mycircuit1.x(range(4))
    mycircuit1.mcx([0, 1, 2], 3)
    mycircuit1.x(range(3))
    
    mycircuit1.measure(3, 0)

    job    = execute(mycircuit1, Aer.get_backend('qasm_simulator'), shots = 1000)
    counts = job.result().get_counts(mycircuit1)
    print("Input:", input_, "Output:", counts)
$\endgroup$
5
  • $\begingroup$ Thanks for the answer. It worked and showed one way of implementing the classical or for 3 qubits. However, I must implement my solution using a total of 4 qubits (circuit = QuantumCircuit(4,1)). Is there any other way to implement the classical or? $\endgroup$
    – Hamideh
    Commented May 4, 2023 at 9:28
  • 1
    $\begingroup$ @Hamideh I've updated the answer to add such a solution. Please have a look. $\endgroup$
    – Tristan Nemoz
    Commented May 4, 2023 at 10:16
  • $\begingroup$ It worked perfectly. Thank you $\endgroup$
    – Hamideh
    Commented May 4, 2023 at 11:06
  • $\begingroup$ What is the reason for putting the last set of Xs after mcx? $\endgroup$
    – Hamideh
    Commented May 4, 2023 at 11:50
  • $\begingroup$ @Hamideh If your goal is only to compute the OR gate, it doesn't serve any purpose. The last layer of $X$ gates ensures that the first qubits are in the same state they were at the beginning of the computation. If you only want to compute the OR gate you can remove them, but if you want to use the OR gate as a routine within another algorithm (just like I did with the second version of or_circ), you have to add them. $\endgroup$
    – Tristan Nemoz
    Commented May 4, 2023 at 11:57
1
$\begingroup$

Maybe I'm not answering the root of your question. I would like to point out that Qiskit has a boolean expression synthesiser that automatically does that:

from qiskit.circuit.classicalfunction import BooleanExpression

circuitXorY = BooleanExpression("x or y").synth()
print(circuitXorY)
q_0: ──■───────
       │       
q_1: ──o────■──
     ┌─┴─┐┌─┴─┐
q_2: ┤ X ├┤ X ├
     └───┘└───┘

With 3 qubits (plus one for the result):

circuitXorYorZ = BooleanExpression("x or y or z").synth()
print(circuitXorYorZ)
q_0: ──■────────────
       │            
q_1: ──o────■───────
       │    │       
q_2: ──o────o────■──
     ┌─┴─┐┌─┴─┐┌─┴─┐
q_3: ┤ X ├┤ X ├┤ X ├
     └───┘└───┘└───┘

You can see how is that implemented without open controls like this:

print(circuitXorYorZ.decompose())
q_0: ───────■───────────────────────────
     ┌───┐  │  ┌───┐                    
q_1: ┤ X ├──■──┤ X ├───────■────────────
     ├───┤  │  ├───┤┌───┐  │  ┌───┐     
q_2: ┤ X ├──■──┤ X ├┤ X ├──■──┤ X ├──■──
     └───┘┌─┴─┐└───┘└───┘┌─┴─┐└───┘┌─┴─┐
q_3: ─────┤ X ├──────────┤ X ├─────┤ X ├
          └───┘          └───┘     └───┘
$\endgroup$
4
  • $\begingroup$ Thanks for the answer. It was insightful. I am trying to build the same circuit in my code but it does not work. I do not know why. $\endgroup$
    – Hamideh
    Commented May 4, 2023 at 9:05
  • 1
    $\begingroup$ I added the same example in terms of mcx. Maybe you can compare with yours. $\endgroup$
    – luciano
    Commented May 4, 2023 at 9:37
  • $\begingroup$ Thanks. At this point, I do not know how to implement CCCX. :-) $\endgroup$
    – Hamideh
    Commented May 4, 2023 at 9:43
  • $\begingroup$ you can do it with MCX (multi-controlled-not) circuit.mcx([0,1,2], [3]). See the docs in qiskit.org/documentation/stubs/… $\endgroup$
    – luciano
    Commented May 4, 2023 at 16:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.