Quantum Processing – Creating Quantum circuit with qiskit.

Posted on Tue 23 September 2025 in misc

Computing is about writing code. Whether it is with punched cards, assembly, Python, or vibe coding using prompts for retards, we need a way to tell the computer which algorithm we want to execute.

I'm currently experimenting with qiskit, the IBM Python library for quantum computing. I don't know if it is good or bad; I just took the first one I found.

Installing qiskit

pip install qiskit qiskit-aer

First program

I won't details the code. I will just gives z small snippet to show how it look like.

import qiskit as q
import qiskit_aer as qaer

# Create a quantum circuit with 2 qbit register and 1 classical register
qc = q.QuantumCircuit(2, 1)

# Add Hadamard gate on qbit 0
qc.h(0)

# Add CNOT Gate between qbit 0 and qbit 1
qc.cx(0, 1)

# measure qbit0 into classical register 1
qc.measure(0, 0)

# print the circuit on console
print(qc)

# creating a simulator to execute quantum circuit
simulator = qaer.AerSimulator(method="statevector")
qc = q.transpile(qc, simulator)

# execute circuit 100 times
job = simulator.run(qc, shots=100)
result = job.result()

# print result of execution
print(result.get_counts())

And the result:

     ┌───┐     ┌─┐
q_0: ┤ H ├──■──┤M├
     └───┘┌─┴─┐└╥┘
q_1: ─────┤ X ├─╫─
          └───┘ ║
c: 1/═══════════╩═
                0
{'0': 57, '1': 43}

— What does the {'0': 57, '1': 43} means ?

Quantum algorithms are intrinsically stochastic. A QBit in superposition state can have 2 different values once measured. So to simulate a measure, we have to run the algorithm several times. Here, we ask the simulator to execute the circuit 100 times. And the result contains the number of times QBit has been measured as "0" and "1". Here, one can see it has been measured 57 times at "0" and 43 times at "1". Giving approximately a 50% chance for both values, which correspond to a QBit that has been put in a superposition state by an Hadamard gate.

Bernstein-Vazirani Algorithm

BV Problem is another quantum problem that can be solve with quantum circuit. Lets assume we have \(s\) a binary string and oracle function \(f_s: \{0, 1\}^n \rightarrow \{0, 1\}\), so that \(f(x)\) is the dot product \(x.s\) module 2: \(f_s(x) = x_1.s_1 \oplus x_2.s_2 \oplus ... \oplus x_n.s_n\)

Ex: \(n=4, s=0101\)

  • \(f_s(0000) = mod_2(0 * 0 + 0 * 1 + 0 * 0 + 0 * 1) = 0\)
  • \(f_s(0001) = mod_2(0 * 0 + 0 * 1 + 0 * 0 + 1 * 1) = 1\)
  • \(f_s(0010) = mod_2(0 * 0 + 0 * 1 + 1 * 0 + 0 * 1) = 0\)
  • \(f_s(0011) = mod_2(0 * 0 + 0 * 1 + 1 * 0 + 1 * 1) = 1\)
  • ...

The goal is to find \(s\) by requesting \(f\).

— What the actual fuck O_O ???

Please, don't force me to find an example involving HR and genre parity in a company...

Anyway, classical algorithm may look like this:

for i in [0, n]:
  s[i] = f(1 << n);

return s

Indeed,

  • \(f(0001)=s_0\)
  • \(f(0010)=s_1\)
  • \(f(0100)=s_2\)
  • \(f(1000)=s_3\)

It require \(n\) evaluation of \(f\) to find \(s\). Lets implement this in qiskit:

Bernstein-Vazirani Classical Algorithm

import qiskit as q
import qiskit_aer as qaer


# Build our secret function.
# this function return a quantum circuit that, given an input x of N Qbits, return f(x) in N+1 QBit
def build_oracle_circuit():
    secret_key = [0, 1, 1]

    # WARNING: 1st value will be on 1st qbit, which is printed on the 1st line when drawing the circuit,
    # but it the "least significant value", so right, when result is printed
    n = len(secret_key)
    qc = q.QuantumCircuit(n + 1)
    for i in range(n):
        s = secret_key[i]
        if s == 0:
            qc.id(i)
        else:
            qc.cx(i, n)
    return qc

# create a curcuit to aks a question to the oracle, and get the oracle answer
def build_ask_oracle_circuit(oracle, question):
    n = oracle.num_qubits

    if len(question) != n - 1:
        raise Exception(f"Question should have {n - 1} values.")

    # Create a cricuit with n qbit and 1 classical bit. As the Oracle answere only with 0 or 1.
    qc = q.QuantumCircuit(n, 1)

    # ================================================
    # Create the question

    for i in range(n - 1):
        if question[i] == 0:
            qc.id(i)
        else:
            qc.x(i)

    # ================================================
    # Plug the oracle

    qc.barrier()

    qc = qc.compose(oracle)

    # ================================================
    # Measure oracle answer

    qc.barrier()

    qc.measure(n - 1, 0)

    return qc


# Helper function to execute given circuit
def execute(circuit):
    simulator = qaer.AerSimulator(method="statevector")
    qc = q.transpile(circuit, simulator)
    job = simulator.run(qc, memory=True, shots=100)
    result = job.result()

    return result


oracle_circuit = build_oracle_circuit()

ask_oracle_circuit = build_ask_oracle_circuit(oracle_circuit, [0, 0, 0])

print(ask_oracle_circuit)

If we execute the circuit, we end up with this:

     ┌───┐  ┌───┐      ░
q_0:  I ├─░─┤ I ├──────░────
     ├───┤  └───┘      ░
q_1:  I ├─░───■────────░────
     ├───┤            ░
q_2:  I ├─░───┼────■───░────
     └───┘  ┌─┴─┐┌─┴─┐  ┌─┐
q_3: ──────░─┤ X ├┤ X ├─░─┤M├
            └───┘└───┘  └╥┘
c: 1/══════════════════════╩═
                           0

On the left, we prepare our inputs. As we ask for [0, 0, 0], the 3 qbits are let as is. On the middle is the oracle circuit. This part is supposed to be unknown. On the right, we measure the oracle answer in register 0.

Let's execute this circuit:

result = execute(ask_oracle_circuit)
print(result.get_counts())
{'0': 100}

This means that all 100 executions return '0'. Which is expected because:

  • \(f([0, 0, 0]) = 0\) whatever \(f\) secret key..
  • We didn't put any qbits into superposition. So result will always be the same.

Let's implement the classical algorithm to find the secret key.

n = oracle_circuit.num_qubits - 1
for i in range(n):
    question = [0] * n
    question[i] = 1

    # build circuit corresponding to question.
    ask_oracle_circuit = build_ask_oracle_circuit(oracle_circuit, question)

    # execute and print
    result = execute(ask_oracle_circuit)
    print(result.get_counts())
{'0': 100}
{'1': 100}
{'1': 100}

So, secret key is [0, 1, 1], with 100% confidence. Cool, we built a classical algorithm and execute it on a quantum computer.

— Could you remind me the prices of a quantum computer ?

A lot. Now, let's write a quantum algorithm that require only 1 evaluation of \(f\).

Bernstein-Vazirani Quantum Algorithm

I won't do the math, just write the program and try to explain it. Let's add this function to our code:

def build_find_hidden_string_circuit(oracle):
    n = oracle.num_qubits

    # build a quantum circuit with n qbits and n-1 classical bits
    qc = q.QuantumCircuit(n, n - 1)

    # ================================================
    # Create the question

    # add H gate to each qbit, so they are in 0/1 superposition
    for i in range(n):
        qc.h(i)

    # add Z gate on the last one, because of reasons
    qc.z(n - 1)

    qc.barrier()

    # ================================================
    # Plug the oracle

    qc = qc.compose(oracle)

    # ================================================
    # Measure oracle answer

    qc.barrier()

    for i in range(n):
        qc.h(i)

    for i in range(n - 1):
        qc.measure(i, i)

    return qc

And execute it:

find_circuit = build_find_hidden_string_circuit(oracle_circuit)
print(find_circuit)
     ┌───┐       ┌───┐       ┌───┐┌─┐
q_0:  H ├──────░─┤ I ├──────░─┤ H ├┤M├──────
     ├───┤       └───┘       ├───┤└╥┘┌─┐
q_1:  H ├──────░───■────────░─┤ H ├─╫─┤M├───
     ├───┤                  ├───┤  └╥┘┌─┐
q_2:  H ├──────░───┼────■───░─┤ H ├─╫──╫─┤M├
     ├───┤┌───┐  ┌─┴─┐┌─┴─┐  ├───┤    └╥┘
q_3:  H ├┤ Z ├─░─┤ X ├┤ X ├─░─┤ H ├─╫──╫──╫─
     └───┘└───┘  └───┘└───┘  └───┘     ║
c: 3/════════════════════════════════╩══╩══╩═
                                     0  1  2

The middle part is still the oracle function, which is unknown. But we built a slightly different question by putting all QBits in a superposition state. It's like if we asked all possible values to Oracle in a single question. Then, instead of measuring the Oracle answer, we first apply an H gate on each qbits and measure the \(n\) first. Because of quantum entanglement, their values depend on the Oracle answer. So their values may be influenced by the last qbit.

Let's execute this circuit:

result = execute(find_circuit)
print(result.get_counts())
{'110': 100}

— Ah, you fail! The secret key is 011, not 110 !

Sorry, but no. The first value of the key is stored in the 1st qbit, i.e., the least significant bit, which is on the right. [0, 1, 1] will be output as 110. It's just a formatting issue, not an algorithm issue.

— Mkay.... Another point. In the classical algorithm, you measured only the last QBit. Whereas in Quantum One, you measured \(n\) Qbits. Of course it's more efficient; you're trying to scam me!!!

Still no. In classical algorithms, I know the first \(n\) qbits are input qbits. So it's useless to measure them. Remember the previous article. Information cannot be lost, so any multi-qbit gate must return the whole input in one way or another. With a classical algorithm, you could measure the first \(n\) qbits, but it won't give you any useful information, and you would still have to do a for loop with \(n\) iterations to get the secret key.

The conclusion is we have a quantum circuit that can find the secret key of an oracle in a single evaluation. In the next article, we will try to understand how this algorithm works.

Takeaways

  • qiskit is a Python library to build and simulate quantum circuits on its computer.
  • To simulate a quantum computer, several runs might be required because of quantum superposition.
  • You can use a quantum computer to execute classical algorithms. But it's not really efficient.