Brefily Introduction
Original problem
This is the solution of qosf - cohort 5 - Task 3 - Find best results, including the original part and the bonus part of the full problem.
Briefly introducing this problem, we are playing tic-tac-toe. You are represented as ‘X’ and ‘O’ as your opponent.
And you find the situation in the figure below, next is your turn.
Try to develop a quantum algorithm to be able to find the best decisions with a higher probability within two rounds.
The blank of the matrix is a qubit, for the state of the X’s is |1> O’s is |0>, and the empty cells are in an unknown state.
Finally, if you think the solution is put the values:
The state output must be | 1100 >.
Bonus
What if we start one step earlier and your opponent has not chosen yet, as shown in the following image, it shows with higher probability the chances of you winning. Please refer to the above considerations.
For the full problem, please refer to the qosf cohort 5.
Original problem
Method
For the original problem, as the hint mentioned in the question, there are only remaining 4 blanks to fill, and the game will end within two rounds.
Therefore, we only need to discuss at most 24 situations (4!) and find whether the situations can make ‘X’ win (NOTE: There are some duplicated situations).
After discussing by brutal force (by listing all the 24 cases), we can easily find out that there are only two reasonable solutions to this problem, including | 1100 > and | 1001 >.
Hence, I adopt the Qiskit - Grover Algorithm to amplify the probabilities of our willing results by designing the oracle and diffuser of Grover’s algorithm.
Since there are two reasonable answers, we only need to run oracle and diffuser for only one time per function.
Quantum circuit - Oracle
To make the states | 1100 > and | 1001 > reflect, I design the oracle circuit as below:
1 | def oracle (nqubits): |
↔
- For the convenience of explanation, I will represent binary as decimal representation in below. For example: | 1100 > is represented by 12, | 1111 > is represented by 15. The willing state-vectors are 9 and 12.
- cz(3,2): making state-vectors include 12, 13, 14, 15 reflect
- toffoli(3,0,2): making exchange between (A ↔ B) for: (9 ↔ 13) and (11 ↔ 15).
After applying this gate, the reflecting state-vectors include **12, 9, 14, 11**
- mct([3,1,0], 2), CCCNOT, for control=[3,1,0], target=2: making exchange between(11 ↔ 15)
After applying this gate, the reflecting state-vectors include **12, 9, 14, 15**
- CCCZ, multi-control z, for control=[3,2,1], target=0: making reflection on 15, the reflecting state-vectors include 12, 9, 14
- mct([3,2,1], 0), CCCNOT for control=[3,2,1], target=0: making exchange between(11 ↔ 14)
After applying this gate, the reflecting state-vectors include **12, 9, 15**
- CCCZ, multi-control z, for control=[3,2,1], target=0: making reflection on 15, the reflecting state-vectors include 12, 9, which are all we demanded.
Quantum circuit - Diffuser
1 | def diffuser(nqubits): |
This part is referred to the 3-qubit example Grover Algorithm of qiskit.
Final Quantum Circuit
1 | n = 4 |
Result
Running jupyterLab on IBM Lab, we can finally find out the result shown as the histogram above.
As shown in the histogram, the output results with higher probabilities are | 1001 > and | 1100 >.
Bonus
Method
Different from the original problem, there are 5 remaining blanks that can be filled.
Besides, we need to find the best decisions with higher probability within two rounds.
Same as solving the original problem as above, I still make a discussion at first to find out the best decisions with higher probability within two rounds.
After discussing by brutal force, we can easily find out that there are still two solutions with the highest probabilities to win under this situation, including | 10001 >, and | 11000 >.
Similarly, I adopt the “Grover algorithm” to amplify the probabilities of our willing results by designing the oracle and diffuser of the algorithm.
Besides, same as above, there are two reasonable answers, hence, we only need to run oracle and diffuser for one time.
NOTE: If you are interested in the discussion to find the best solution, you can reference the file ‘discu\brufo’ under the same GitHub repository. However, this file is just the calculation process when I solved this problem which is not organized. It is only provided as a supplementary that the content is relatively messy.
Quantum circuit - Oracle
1 | # oracle: make |10001> and |11000> reflect |
- For the convenience of explanation, I will represent binary as decimal representation below. For example: | 10000 > is represented by 16, | 11000 > is represented by 24. The willing states are 17 and 24.
- In this part, I first use the CZ gate to reflect 8 state-vectors (24-31).
- cz(4,3): At this point, only 24 of the reflected state is what we are willing to be reflected.
- qc.toffoli(4,0,3): Next, I use the CCX gate to exchange the amplitude of (17 ↔ 25), (19 ↔ 27), (21 ↔ 29) and (23 ↔ 31).
- At this time, there are a total of reflected state-vectors are 24, 17, 26, 19, 28, 21, 30, 23 with only 24 and 17 are the desired states needed to reflect.
- After reflecting on those needed state-vectors, there are some state-vector that don’t need to be reflected. Hence, we need to reflect them back to be positive.
- The approach I took is to swap each state-vector with only three qubits are measured in | 1 > by using the CCCX gate to swap with their corresponding state-vectors with 4 qubits are measured in | 1 >.
- Then exchanges the state-vector with 4 qubits are measured in | 1 > with | 11111 > by using the CCCCX gate.
- Finally, we use the CCCCZ gate to reflect | 11111 > as a positive state-vector. Then we can successfully make the state-vector reflected back to the positive amplitude.
The processes in detail are shown below:
Making the state 30 reflected back to positive, the remaining negative state-vectors are 24, 17, 26, 19, 28, 21, 23
1
2
3
4qc.mct([4,3,2,1], 0) # 3-1, CCCCX
qc.h(0) # 3-2, CCCCZ
qc.mct([4,3,2,1], 0)
qc.h(0)Making the state 23 reflected back to positive, the remaining negative state-vectors are 24, 17, 26, 19, 28, 21
1
2
3
4
5qc.mct([4,2,1,0], 3) # 4-1, CCCCX
# 4-2, CCCCZ
qc.h(0)
qc.mct([4,3,2,1], 0)
qc.h(0)Making the state 26 reflected back to positive, the remaining negative state-vectors are 24, 17, 19, 28, 21
- Making exchange between 26 ↔ 30 and 27 ↔ 31. The exchange between 27 and 31 have no impact.Making exchange between 30 ↔ 31.
1
qc.mct([4,3,1], 2) # 5, CCCX
Making reflection on 31.1
qc.mct([4,3,2,1], 0) # 6-1, CCCCX
1
2
3
4# 6-2, CCCCZ
qc.h(0)
qc.mct([4,3,2,1], 0)
qc.h(0)
- Making exchange between 26 ↔ 30 and 27 ↔ 31. The exchange between 27 and 31 have no impact.
Making the state 19 reflected back to positive, the remaining negative state-vectors are 24, 17, 28, 21
Making exchange between 19 ↔ 27 and 23 ↔ 31. The exchange between 23 and 31 have no impact.
1
qc.mct([4,1,0], 3) # 7, CCCX
Making exchange between 27 ↔ 31.
1
qc.mct([4,3,1,0], 2) # 8-1, CCCCX
Making reflection on 31.
1
2
3
4# 8-2, CCCCZ
qc.h(0)
qc.mct([4,3,2,1], 0)
qc.h(0)
Making the state 28 reflected back to positive, the remaining negative state-vectors are 24, 17, 21
- Making exchange between 28 ↔ 29 and 30 ↔ 31. The exchange between 30 and 31 have no impact.
1
qc.mct([4,3,2], 0) # 9, CCCX
- Making exchange between 29 ↔ 31
1
2
3
4
5
6
7
8
9
10
11
12qc.mct([4,3,2,0], 1) # 10-1, CCCCX
```
* Making exchange between **29 ↔ 31**.
```python=
qc.mct([4,3,2,0], 1) # 10-1, CCCCX
```
* Making reflection on **31**
```python=
# 10-2, CCCCZ
qc.h(0)
qc.mct([4,3,2,1], 0)
qc.h(0)
- Making exchange between 28 ↔ 29 and 30 ↔ 31. The exchange between 30 and 31 have no impact.
Making the state 21 reflected back to positive, the remaining negative state-vectors are 24, 17
- Making exchange between 21 ↔ 23 and 29 ↔ 31. The exchange between 29 and 31 have no impact.
1
qc.mct([4,2,0], 1) # 11, CCCX
- Making exchange between 23 ↔ 31
1
qc.mct([4,2,1,0], 3) # 12-1, CCCCX
- Making reflection on 31
1
2
3
4# 12-2, CCCCZ
qc.h(0)
qc.mct([4,3,2,1], 0)
qc.h(0)
- Making exchange between 21 ↔ 23 and 29 ↔ 31. The exchange between 29 and 31 have no impact.
Finally, we got that only the state-vectors 24, and 17 are reflected in negative.
Quantum circuit - Diffuser
This part is referred to the 3-qubit example Grover Algorithm of qiskit.
Final Quantum Circuit
1 | n = 5 |
Result
Running jupyterLab on IBM Lab, we can finally find out the result shown as the histogram above.
As shown in the histogram, the output results with higher probabilities are | 10001 > and | 11000 >.
Discussion by brutal force
The discussion make by brutal force for the classical situation is shown in the “discu_brufo.pdf” file.
Full code
For the full executable code, please refer to my Github Repository.
Conclusion
In this article, we introduce the solution of task3 of QC qosf Mentorship program cohort 5.
This article focuses on describing how to build quantum circuits of the oracle function of Grover’s Algorithm by describing everything that happens after applying each gate in the oracle.
Question
If there is any question or discussion, please feel free to send an email to me.