COMS 4281 Intro to Quantum Computing Problem Set 5 Qubit Tug-of-War
Due date: December 18, 11�59pm.
For the second part of Problem Set 5, you should get into teams of at most 3 (this will be
strictly enforced), and as a team you will come up with strategies for a quantum video
game we call Qubit Tug-of-War.
Please register your team with by filling out
https://forms.gle/z5FvHubfoZvsPqxk6
Rules of the game
There are two teams in this game, Team and Team . They take turns getting control of
a rotating qubit . In between the teams’ turns, the qubit rotates by either or
depending on the current direction of rotation. At the beginning, the qubit starts rotating in
the direction of .
During their turn, each team can choose to perform an action from their hand (think of an
action as a “card”). Here are possible actions that a team can have:
�. Measure: this measures in the standard basis.
�. X: apply Pauli gate to .
�. Z: apply Pauli gate to .
�. H: apply the Hadamard gate to .
�. R: reverse the direction of the qubit rotation (i.e. qubit gets rotated by instead of
and vice versa).
A team can also choose to pass (do nothing). If they perform an action, it gets removed
from their hand.
Each team starts with an empty hand. At random intervals, each team gets a random action,
unless they already have actions in a hand, or have already received the maximum of
actions throughout the game.
At the start of their turn, each team learns:
�. What actions were performed in the previous round (by Team and Team ).
�. If there were measurements, what the outcome were.
Important: each team is responsible for calculating the state of the qubit based on the
history of actions and measurement results.
There are a total of turns for each team. At the end, the qubit is measured, and
if the outcome is , then Team wins.
Game Parameters
We’ve specified the parameters with default values as follows:
Number of rounds:
Action budget (this maximum number of actions a team can receive):
Hand size (maximum number of actions they can have at one time):
(angle of rotation):
The relative frequency of the actions are as follows:
Measure: 5%
X, Y, H : 25%
Reverse: 20%
Initial state of qubit: .
Programming your QToW Bot
Instead of playing this game in person, your team will program a bot to play for you. Your
bot will be pitted against other teams’ bots.
We will provide a few basic bots to help you develop your own strategy. One of the bots is
called the RandomBot , which chooses actions randomly.
T = 100 |ψ⟩
|+⟩ = (|0⟩ + |1⟩)1
In [ ]: %run GamePlayer.py
class RandomBot(GameBot):
def play_action(self,
team: int,
round_number: int,
hand: List[GameAction],
prev_turn: List) -> Optional[GameAction]:
#this is the probability that it chooses to play an action
#if the hand is non-empty and we flip a coin and it lands heads with pr
#choose a random action
if len(hand) > 0 and np.random.random() < p:
action = random.choice(hand)
return action
#otherwise, don't play an action
return None
All bots are a Python class that inherits GameBot . There is just one function to implement,
called play_action , which (aside from self ), has the following arguments:
�. team : this indicates whether the bot is team 0 or team 1.
�. round_number : this indicates which round (between and ) the bot is
currently playing
�. hand : this is a list of GameAction s that is available for the bot to play. There are
several GameActions that can be played:
GameAction.MEASURE
GameAction.PAULIX
GameAction.PAULIZ
GameAction.HADAMARD
GameAction.REVERSE
So an example of a hand could be the following list:
[GameAction.MEASURE,GameAction.PAULIZ,GameAction.PAULIZ,GameAction.REVERS
Meaning that the bot can measure, apply Pauli Z (twice), or reverse the direction of the
qubit rotation.
Every few rounds, a random action will be added to the bot's hand, unless (a) the hand is
full, or (b) actions have already been added.
�. prev_turn : this is a Python dictionary that specifies what happened in the previous
turns. The keys of this dictionary are: team0_action , team1_action ,
team0_measurement , team1_measurement . The team0/1_action entries store
the GameAction that was performed by the team, or None if they didn't perform an
action. If a team performed a measurement action, then the team0/1_measurement
entries indicate the result of a measurement(either [1,0] or [0,1] to indicate
collapsing to or ). If the team didn't perform a measurement action, then this
entry will be set to None .
For example, suppose in the previous turn Team used a HADAMARD action and Team
measured. Then the dictionary would look like this:
prev_turn = {'team0_action': GameAction.HADAMARD, 'team1_action':
GameAction.MEASURE, 'team0_measurement': None, 'team1_measurement': =
You may find it helpful to design a bot, for example, that chooses its actions based on the
history of yours and the other team's past actions.
Here's another example of a bot. It's not very intelligent, but should illustrate some things
you can do.
In [ ]: class WeirdBot(GameBot):
def play_action(self,
team: int,
Let's pit RandomBot versus WeirdBot against each other! When creating the bots, you
need to pass the name of the bot as an argument.
To see a transcript of the game, you can run the following code. It shows you the state of
the qubit at each round, the actions that were performed, and which actions were added to
the bots' hands. If you're running this in IBM Quantum Lab, you probably want to right click
on the output cell and select "Enable scrolling for outputs".
Now try creating your own bot by writing code below.
round_number: int,
hand: List[GameAction],
prev_turn: List) -> Optional[GameAction]:
#if the round is even, check if there’s a PauliX operation, and play it
if GameAction.PAULIX in hand and team % 2 == 0:
return GameAction.PAULIX
#otherwise if round is odd, try to measure
if GameAction.MEASURE in hand and team % 2 == 1:
return GameAction.MEASURE
return None
In [ ]: #create the bots
weirdbot = WeirdBot(“The Weirdos”)
randombot = RandomBot(“The Randos”)
#create the gameplayer with the weirdbot as team |0> and randombot as team |1>
gp = GamePlayer(weirdbot,randombot)
#play the game, get the winning state
winning_state = gp.play_rounds()
if winning_state[0] == 1:
print(“===Weird bot beats Random bot!===”)
print(“===Random bot beats Weird bot!===”)
In [ ]: #get the event log
log = gp.get_event_log()
print(log)
In [ ]: ”’
Insert high-level explanation of your strategy here. Why did you design this st
When should it work well, and when should it have trouble?
class MyStrategy(GameBot):
Initialize your bot here. The init function must take in a bot_name.
You can use this to initialize any variables or data structures
Submitting your bots
Once you have a bot ready to play against others, you should copy your Bot code (e.g. the
MyStrategy class) into a separate python file (see the example file example_bot.py )
and also include the following includes:
from typing import List, Optional import numpy as np import random
from GamePlayer import *
Then, visit the Qubit Tug-of-War website at https://henryyuen.net/fall2022/qtugofwar and
click “Upload your bot”. You will need your Team ID. If you don’t have one, register your
team at https://forms.gle/z5FvHubfoZvsPqxk6 and e-mail Prof. Yuen to get a Team ID.
A tournament between all the bots will be played daily, and the Leaderboard will be updated
to show the current performance. You can browse the statistics and examine sample
transcripts of games.
Some constraints
Your bot python file cannot exceed 30kb.
If your bot crashes or throws an error, it automatically loses.
If your bot runs for too much time, it automatically loses.
Do not include any custom python packages, because it is unlikely we will have them.
The Leaderboard will be active from December 1 to December 15. It will not be updated
after December 16 so there will be a couple days for teams to optimize their bots in secret!
Your bot is due December 18, 11�59pm. A final Tournament will be played on December 19
to determine the winning teams.
Late bots are not accepted!
to keep track of things in the game
def __init__(self,bot_name):
self.bot_name = bot_name #do not remove this
def play_action(self,
team: int,
round_number: int,
hand: List[GameAction],
prev_turn: List) -> Optional[GameAction]:
##### IMPLEMENT AWESOME STRATEGY HERE ##################
#######################################################
return None
Every team must work independently on their bot (teams should not share code). Your bots
will be graded in the following way. Points will be awarded based on a combination of:
�. Effort and creativity,
�. Whether your code includes in the beginning a discussion about your strategy and your
rationale behind the design choices, and
�. Performance against other bots.
As a target, you should try to design a bot that consistently beats RandomBot at least
60% of the time.