Skip to article frontmatterSkip to article content

Section1: Perform Quantum Computing

Quantum Tokyo

TASK1.1: Define Pauli Operators

In quantum computing, a Pauli operation refers to applying one of the three Pauli matrices—X, Y, or Z—to a qubit.

  • X (Pauli-X): Bit-flip (like a classical NOT gate).
  • Z (Pauli-Z): Phase-flip (adds a relative phase of −1 to 1|1⟩).
  • Y (Pauli-Y): Combination of bit-flip and phase-flip.
X=σx=[0110],Y=σy=[0ii0],Z=σz=[1001]X = \sigma_x = \begin{bmatrix} 0 & 1 \\ 1 & 0 \end{bmatrix}, \quad Y = \sigma_y = \begin{bmatrix} 0 & -i \\ i & 0 \end{bmatrix}, \quad Z = \sigma_z = \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix}
  1. Which matrix is generated by the following code?
from qiskit.quantum_info import Pauli
p = Pauli("XZ")
print(p.to_matrix())

a. [0100100000010010]\begin{bmatrix}0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & -1 \\ 0 & 0 & -1 & 0 \end{bmatrix}

b. [0010000110000100]\begin{bmatrix}0 & 0 & 1 & 0 \\ 0 & 0 & 0 & -1 \\ 1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \end{bmatrix}

c. [1000010000100001]\begin{bmatrix}1 & 0 & 0 & 0 \\ 0 & -1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & -1 \end{bmatrix}

d. [0i00i000000i00i0]\begin{bmatrix}0 & -i & 0 & 0 \\ i & 0 & 0 & 0 \\ 0 & 0 & 0 & i \\ 0 & 0 & -i & 0 \end{bmatrix}

answer

Answer: a

The label "XZ" corresponds to the tensor product XZX \otimes Z. The to_matrix() method constructs the full matrix representation. Option (a) matches this result, as it applies XX on the first qubit and ZZ on the second qubit.

from qiskit.quantum_info import Pauli
p = Pauli("XZ")
print(p.to_matrix())
[[ 0.+0.j  0.+0.j  1.+0.j  0.+0.j]
 [ 0.+0.j  0.+0.j  0.+0.j -1.+0.j]
 [ 1.+0.j  0.+0.j  0.+0.j  0.+0.j]
 [ 0.+0.j -1.+0.j  0.+0.j  0.+0.j]]
  1. Which of the following input formats are valid when creating a Pauli object?

a. Pauli("IXYZ")
b. Pauli([1, 0, 1, 1])
c. Pauli((z_bits, x_bits))
d. Pauli(np.array([[0, 1],[1, 0]]))

answer

Answer: a, c

A Pauli object can be constructed from:

  • A string label such as "IXYZ".
  • A tuple of (z_bits, x_bits) describing the binary representation of the Pauli.

Raw integer lists (option b) and numpy matrices (option d) are not valid inputs. For matrices, one must use the Operator class instead.

  1. What label is printed by the following code?
from qiskit.quantum_info import Pauli
p = Pauli("XZ")
q = Pauli("ZI")
r = p.compose(q)
print(r.to_label())

a. "YZ"
b. "iZZ"
c. "XI"
d. "iYZ"

answer

Answer: d

When composing Pauli("XZ") with Pauli("ZI"), the operation corresponds to matrix multiplication in the correct qubit order. The compose() method applies the second Pauli on the right, consistent with operator composition.

  1. Which of the following best describes the role of the dot() method in the Pauli class?

a. Multiplies two Pauli operators and returns a new Pauli
b. Converts the Pauli to a matrix and computes the inner product
c. Combines two Pauli operators by tensor product
d. Generates the Hamiltonian representation of a Pauli operator

answer

Answer: a

Composition compose() by default is defined as left matrix multiplication, while dot() is defined as right matrix multiplication.
Setting the front=True kwarg changes this to right multiplication and is equivalent to the dot() method: A.dot(B) == A.compose(B, front=True)

from qiskit.quantum_info import Pauli
p = Pauli("X")
q = Pauli("Z")
r = p.dot(q)
print(r.to_label())
-iY

TASK 1.2: Apply quantum operations

  1. Which method appends one or more instructions to the end of the circuit, modifying the circuit in place?

a. compose
b. append
c. to_instruction
d. decompose

answer

The answer is b.

append is the method that directly adds an instruction (such as a gate or an instruction object) to the end of a circuit. compose combines two circuits, to_instruction converts a circuit into a single instruction, and decompose expands instructions into their definitions.

  1. By default, what does QuantumCircuit.compose(other) return when called without inplace=True?

a. It mutates the left-hand circuit and returns None.
b. It returns a new combined circuit.
c. It mutates the right-hand circuit and returns it.
d. It raises an error unless inplace is specified.

answer

The answer is b.

By default, compose returns a new circuit object that represents the composition, leaving the original circuit unchanged unless inplace=True is specified.

from qiskit import QuantumCircuit

left = QuantumCircuit(1, name="left")
left.h(0)

right = QuantumCircuit(1, name="right")
right.x(0)

# 1) default(inplace=False)
combined = left.compose(right)   # ← new circuit
print("left unchanged:\n", left.draw())
print("right unchanged:\n", right.draw())
print("combined (left then right):\n", combined.draw())

# inplace=True
left2 = QuantumCircuit(1, name="left2")
left2.h(0)

ret = left2.compose(right, inplace=True)
print("left2 mutated:\n", left2.draw())
print("ret is left2?:", ret is left2)
left unchanged:
    ┌───┐
q: ┤ H ├
   └───┘
right unchanged:
    ┌───┐
q: ┤ X ├
   └───┘
combined (left then right):
    ┌───┐┌───┐
q: ┤ H ├┤ X ├
   └───┘└───┘
left2 mutated:
    ┌───┐┌───┐
q: ┤ H ├┤ X ├
   └───┘└───┘
ret is left2?: False
  1. Which code correctly composes qc_b onto qc_a so that qc_b’s qubits (0, 1) map to qc_a’s qubits (1, 3), without mutating qc_a?

a. qc_a.compose(qc_b, qubits=[1, 3])
b. qc_a.compose(qc_b, [1, 3], inplace=True)
c. qc_a.append(qc_b, [1, 3])
d. qc_b.compose(qc_a, qubits=[1, 3])

answer

The answer is a.

The compose method allows remapping qubits via the qubits argument. This lets you map qc_b’s qubits (0, 1) to any chosen positions in qc_a, e.g. (1, 3).
Using append requires an Instruction, not a QuantumCircuit.

  1. Which snippet converts a subcircuit to an instruction and appends it to another circuit?

a.

inst = qc_b.to_instruction()
qc_a.append(inst, [1, 3])

b.

inst = qc_b.to_gate()
qc_a.compose(inst, [1, 3])

c.

inst = qc_b.compose()
qc_a.append(inst, [1, 3])

d.

inst = qc_b.control()
qc_a.append(inst, [1, 3])
answer

The answer is a.

to_instruction() converts a circuit into a single instruction object. That instruction can then be appended to another circuit, specifying which qubits it acts on.

  1. Select all that apply: Which statements about turning circuits into reusable operations are correct?

a. to_gate() requires the source circuit to be unitary.
b. A Gate produced by to_gate() can be made controlled via .control().
c. to_instruction() returns a Gate.
d. to_gate() always mutates the original circuit.

answer

The answer is a, b.

to_gate() requires a unitary circuit and produces a Gate object that supports .control(). to_instruction() is more general and produces an Instruction. Neither mutates the source circuit.

  1. What happens if you call qc.barrier() with no qubit arguments?

a. It inserts no operation.
b. It raises an error.
c. It applies a barrier to all qubits in the circuit.
d. It applies a barrier only to measured qubits.

answer

The answer is c.

Calling barrier() with no arguments applies a barrier to all qubits in the circuit, enforcing that no instructions cross the barrier during optimization or scheduling.

  1. Which statement about decompose() on a circuit is correct?

a. It mutates the circuit to expand each instruction into its definition.
b. It returns a new circuit with instructions expanded into their definitions.
c. It removes all non-unitary operations from the circuit.
d. It only affects instructions with labels.

answer

The answer is b.

decompose() returns a new circuit in which higher-level instructions are expanded into their definitions. It does not modify the original circuit in place.

  1. The QuantumCircuit.data attribute is best described as which of the following?

a. A list of Instruction objects only.
b. A list of CircuitInstruction objects, each with an operation and its qubits/clbits.
c. A tuple of (operation, parameters) pairs.
d. A dictionary keyed by gate names.

answer

The answer is b.

QuantumCircuit.data is a list of CircuitInstruction objects. Each contains an operation along with the associated quantum and classical arguments (qubits, clbits).

from qiskit.circuit import QuantumCircuit
qc = QuantumCircuit(1)
qc.x(0)
print(qc.data)
[CircuitInstruction(operation=Instruction(name='x', num_qubits=1, num_clbits=0, params=[]), qubits=(<Qubit register=(1, "q"), index=0>,), clbits=())]
  1. Which call correctly applies a custom 4×4 unitary matrix U to qubits [0, 1] with label "U"?

a. qc.unitary(U, [0, 1], label="U")
b. qc.append(U, [0, 1], label="U")
c. qc.compose(U, [0, 1], inplace=True)
d. qc.to_gate(U, [0, 1], label="U")

answer

The answer is a.

The unitary() method attaches an arbitrary unitary matrix as an operation acting on specified qubits. It optionally takes a label for display.

  1. Which method applies a multiple-controlled Z-axis rotation of angle lam with control qubits in controls and target t?

a. qc.mcrx(lam, controls, t)
b. qc.mcry(lam, controls, t)
c. qc.mcrz(lam, controls, t)
d. qc.crz(lam, controls, t)

answer

The answer is c.

mcrz(lam, controls, t) applies a multiple-controlled Rz rotation with the given angle lam. The controls define the condition, and t specifies the target qubit.

  1. Which statement about append and CircuitInstruction is correct?

a. When passing a CircuitInstruction to append, you must also pass qargs and cargs.
b. Passing a CircuitInstruction to append forbids also passing separate qargs or cargs.
c. append cannot accept CircuitInstruction objects.
d. append never returns a handle to the added instruction(s).

answer

The answer is b.

If you pass a CircuitInstruction object to append, you must not also pass explicit qargs or cargs. Doing so would cause an error because the instruction already encapsulates that information.

  1. Which snippet uses the circuit library to append a single-qubit H operation to qubit 0?

a. qc.append(HGate(), [0])
b. qc.compose(HGate(), [0])
c. qc.to_instruction(HGate(), [0])
d. qc.control(HGate(), [0])

answer

The answer is a.

Appending HGate() to qubit 0 using qc.append(HGate(), [0]) is the correct way to use the library-defined Hadamard gate.

  1. You have built a two-qubit subcircuit qc_b and wish to create a controlled version of it with one control and two targets. Which sequence achieves this before appending to qc_a?

a.

gate = qc_b.to_gate().control()
qc_a.append(gate, [c, t0, t1])

b.

gate = qc_b.to_instruction().control()
qc_a.append(gate, [c, t0, t1])

c.

gate = qc_b.compose().control()
qc_a.append(gate, [c, t0, t1])

d.

gate = qc_b.control()
qc_a.append(gate, [c, t0, t1])
answer

The answer is a.

First, convert the subcircuit into a Gate using to_gate(), then call .control() to make a controlled version. This can then be appended to another circuit with the control and target qubits specified.

  1. Which statement about qubit remapping when composing circuits is correct?

a. compose does not support remapping; qubits must match by index.
b. You can specify a list of target qubit indices via the qubits argument.
c. Remapping is only available with append, not compose.
d. Remapping requires both circuits to have the same number of classical bits.

answer

The answer is b.

When composing circuits, you can remap qubits by providing a list of target indices to the qubits argument in compose. This allows flexible placement of subcircuits within larger circuits.

  1. Select all that apply: Which methods can convert a circuit into a reusable operation that can be inserted into other circuits?

a. to_instruction()
b. to_gate()
c. decompose()
d. append()

answer

The answer is a, b.

Both to_instruction() and to_gate() convert a QuantumCircuit into an object that can be appended as a reusable operation in another circuit. decompose() and append() serve different purposes.

  1. Which method returns the number of layers of quantum gates that must be executed sequentially in a circuit?

a. size()
b. depth()
c. count_ops()
d. width()

answer

The answer is b.

depth() returns the number of sequential layers of operations (the circuit depth). This measures how many steps are needed to execute the circuit if gates on different qubits can be run in parallel. size() counts all operations, count_ops() returns a dictionary of operation counts, and width() measures the total number of qubits and classical bits used.

  1. What is a key conceptual difference between an Instruction and a QuantumCircuit in Qiskit?

a. Instructions are immutable, while circuits are typically mutable.
b. Circuits can only contain unitary operations, while instructions can include non-unitary ones.
c. Instructions support barriers, while circuits do not.
d. Circuits are immutable, while instructions are mutable.

answer

The answer is a.

An Instruction is immutable; once created, its definition cannot be altered. A QuantumCircuit is mutable, meaning it can be changed by appending or composing new instructions. This immutability allows instructions to be reused consistently across different circuits.

  1. Which statement about parameterized circuits in Qiskit is correct?

a. Parameters must be defined with numerical values at circuit creation time.
b. Undefined parameters can be assigned values later using assign_parameters().
c. The parameters attribute of a circuit always returns an empty list.
d. Parameterized circuits cannot be transpiled.

answer

The answer is b.

Qiskit allows creating parameterized circuits with undefined symbolic parameters. Later, you can bind these symbols to concrete values using assign_parameters(). This feature enables efficient reuse of a single circuit structure across many parameter values.

  1. Which object type is used to represent a symbolic parameter in a Qiskit circuit?

a. ParameterView
b. ParameterExpression
c. Parameter
d. SymbolicVariable

answer

The answer is c.

The Parameter class is used to define symbolic parameters in a circuit. While ParameterExpression represents algebraic combinations of parameters, the atomic symbolic unit itself is Parameter.

  1. Why are parameterized circuits useful in variational algorithms?

a. They reduce the number of qubits required by an algorithm.
b. They allow constructing and transpiling the circuit once, while reusing it with different parameter values.
c. They automatically parallelize parameter updates across multiple backends.
d. They eliminate the need for classical optimizers.

answer

The answer is b.

Parameterized circuits are particularly useful in variational algorithms because you can transpile the circuit once and reuse it with different parameter values during classical optimization. This avoids repeatedly recompiling the circuit and improves performance.