Let us first rewrite the problem into a more manageable form.
We define
X=(0110),R=(exp(−2n2πi)00exp(2n2πi)).
In fact, the operation g(m,k) can be represented by the matrix
XmRk.
Thus, we can rewrite the problem as follows.
Implement an oracle O satisfying the following transition on a quantum circuit qc with n qubits.
For any pair of integers (m,k) satisfying 0≤m<2 and 0≤k<2n, the oracle satisfies
∣m⟩∣k⟩nO∣m′⟩∣k′⟩n.
Here, 0≤m′<2 and 0≤k′<2n must satisfy
Xm′Rk′=XmafterRkafterXmRkXmbeforeRkbefore.
Now, let us think about how to solve this problem.
We define the oracle E as the transformation to the state defined in B2 and B3:
∣m⟩∣k⟩EE(m,k)
If we can construct such an oracle, we can solve the problem as follows.
∣m⟩∣k⟩EE(m,k)B2B3E(m′,k′)E†∣m′⟩∣k′⟩
By using the quantum circuits for QFT, A4, and A5, we can construct a quantum state that closely resembles E(m,k).
Finally, we apply circuits such as A2 and A3 to make minor adjustments.
import mathfrom qiskit import QuantumCircuit, QuantumRegisterfrom qiskit.circuit.library import ZGate, RZGate, HGate, XGatedef A2(n: int) -> QuantumCircuit: m, k = QuantumRegister(1), QuantumRegister(n) qc = QuantumCircuit(m, k) qc.x(k) qc.compose(HGate().control(len(k)), [*k, m[0]], inplace=True) qc.x(k) return qcdef A3(n: int) -> QuantumCircuit: m, k = QuantumRegister(1), QuantumRegister(n) qc = QuantumCircuit(m, k) qc.x(m[0]) qc.x(k) qc.compose(XGate().control(len(k)), [*k, m[0]], inplace=True) qc.x(k) return qcdef A3_alt(n: int) -> QuantumCircuit: a, b, c = QuantumRegister(1), QuantumRegister(1), QuantumRegister(n - 1) qc = QuantumCircuit(a, b, c) qc.cx(b[0], a[0]) qc.x(c) qc.compose(XGate().control(len(c) + 1), [*c, *b, *a], inplace=True) qc.x(c) return qcdef A4(n: int) -> QuantumCircuit: L = n + 1 qc = QuantumCircuit(L) for i in range(L.bit_length()): for j in range(0, L - (2 ** i), 2 ** (i + 1)): qc.swap(j, j + (2 ** i)) return qcdef A5_alt(n: int) -> QuantumCircuit: b, c = QuantumRegister(1), QuantumRegister(n - 1) qc = QuantumCircuit(b, c) for i in range(n-1): qc.compose(XGate().control(1), [b[0], c[i]], inplace=True) for i in reversed(range(1, n-1)): qc.compose(XGate().control(i+1), [b[0]] + [c[j] for j in range(i)] + [c[i]], inplace=True) qc.compose(XGate().control(1), [b[0], c[0]], inplace=True) return qcdef B2(n: int, m_left: int, k_left: int) -> QuantumCircuit: a, b, c = QuantumRegister(1), QuantumRegister(1), QuantumRegister(n - 1) qc = QuantumCircuit(a, b, c) qc.x(c) if m_left: qc.compose(ZGate().control(len(c)), [*c, a[0]], inplace=True) if k_left % 2: qc.compose(ZGate().control(len(c)), [*c, b[0]], inplace=True) qc.x(c) theta = 2 * math.pi / 2 ** (n - 1) for i in range(n - 1): angle = theta * k_left * (2 ** i) qc.compose(RZGate(angle).control(1), [c[i], a[0]], inplace=True) if m_left: qc.compose(A3(n - 1), [a[0], *c], inplace=True) return qcdef B3(n: int, m_right: int, k_right: int) -> QuantumCircuit: a, b, c = QuantumRegister(1), QuantumRegister(1), QuantumRegister(n - 1) qc = QuantumCircuit(a, b, c) qc.x(c) if m_right: qc.compose(ZGate().control(len(c)), [*c, a[0]], inplace=True) if k_right % 2: qc.compose(ZGate().control(len(c)), [*c, b[0]], inplace=True) qc.x(c) if m_right: qc.compose(A3(n - 1), [b[0], *c], inplace=True) theta = 2 * math.pi / 2 ** (n - 1) for i in range(n - 1): angle = theta * k_right * (2 ** i) qc.compose(RZGate(angle).control(1), [c[i], b[0]], inplace=True) return qcdef qft(n: int) -> QuantumCircuit: qc = QuantumCircuit(n) for i in reversed(range(n)): qc.h(i) for j in reversed(range(i)): qc.cp(math.pi / 2 ** (i - j), j, i) for i in range(n // 2): qc.swap(i, n - i - 1) return qcdef dqft(n: int) -> QuantumCircuit: a, b, c = QuantumRegister(1), QuantumRegister(1), QuantumRegister(n-1) qc = QuantumCircuit(a, b, c) qc.compose(qft(n), qubits=[*b, *c], inplace=True) qc.compose(A4(n - 1), qubits=[*b, *c], inplace=True) qc.compose(A5_alt(n), qubits=[*b, *c], inplace=True) qc.compose(A2(n - 1), qubits=[*a, *c], inplace=True) qc.compose(A3(n - 1), qubits=[*b, *c], inplace=True) qc.compose(A3_alt(n), qubits=[*a, *b, *c], inplace=True) return qcdef solve(n: int, m_before: int, k_before: int, m_after: int, k_after: int) -> QuantumCircuit: qc = QuantumCircuit(n + 1) qc.compose(dqft(n), inplace=True) qc.compose(B3(n, m_before, k_before), inplace=True) qc.compose(B2(n, m_after, k_after), inplace=True) qc.compose(dqft(n).inverse(), inplace=True) return qc
Follow-up
Background for problems B and Ex
Problem B1 is based on the following fundamental idea:
To transform the state ∣k⟩ into ∣k+a⟩, it suffices to apply the Fourier transform to ∣k⟩, then apply the phase gate, and finally perform the inverse Fourier transform to return to the computational basis.
Here, the addition "+" refers to the group operation in the cyclic groupZ/2nZ.
Now, the theme of this contest is to explore whether a similar approach is possible for a more structurally complex group: the dihedral groupD2n.
The key difference between the dihedral group and the cyclic group is that the dihedral group is non-commutative in general.
Interestingly, there exists an operation analogous to the Fourier transform in the context of the dihedral group. This is the oracleE. If you look closely at the formula for E(m,k), you will notice that both m and k appear entirely in the exponent, which strongly resembles the structure of a standard Fourier transform.
In this contest, we encourage you to focus on the following key insights:
Problem B2: To compute left multiplication by a group element, it suffices to apply an operation to the left bit even in the Fourier basis.
Problem B3: To compute right multiplication, applying an operation to the right bit in the Fourier basis is sufficient.
If you're wondering where the expression for E(m,k) comes from, we encourage you to look into group representation.
And if you think, “I’d never come up with a circuit for oracle E," we suggest taking a look at the hints provided below.