You are expected to complete this assignment individually. If you need help, you are invited to come to virtual office hours and/or ask questions on Piazza. Clarification questions about the assignments may be asked publicly. Once you have specific bugs related to your code, make the posts private. Piazza is your community resource - please use those as discussions amongst yourselves. We are not monitoring it all day, rather we each have check-in times once a day. Therefore, you need to start early enough to wait for feedback and/or build a vibrant, supportive community that helps each other while we are completing other necessary tasks (research, developing assignments, preparing for lecture, performing advising tasks, etc.).
In this homework, you will implement a qubit. The first half of the course builds upon this code week by week.
You will submit several files for this assignment, including files from the warmup and the homework (qubit.py, testharness ). You will submit your work in a zip file to Gradescope. More detailed submission instructions will come later.
Code inevitably breaks: users may provide incorrect inputs, existing data may be incorrect, or the method may encounter an unexpected edge case. When errors occur, the question becomes, "What should we do?" and "How can we notify the caller that an error occured?" Different situations necessitate different responses. Sometimes, we'll need to just give a warning to the user, othertimes we'll need to completely halt execution.
Error handling capabilities vary by language; in Python, the keyword throw is reserved to throw exceptions. In this course, we will print the error message in a special way (see below). If there is an opportunity, we will designate a specific return value for an error condition. If there is no available return value, then we will exit from within the method.
print("error: too many widgets for the number of grommets"); print("error: need ten boondoggles, but only have "+ num_bds); return False
def surface_area_cylinder( height, radius): print("surface_area_cylinder not yet implemented") return 0.0
val = surface_area_cylinder(3.5, 7.9)
First get this compiling and running. It won't do anything useful, but this will mean that your code will compile and execute with our infrastructure. This must work in order to get any points in this course. Do this first, not last.
Why are skeletons important? This code guides your thinking about the key methods / classes that need to be implemented.
From a global perspective, skeletons help you better structure code. For example, if you'll need to sort arrays to be both ascending and descending, it may be easier to have a single def sort_arrays with an ascending=False variable.
From a more granular perspective, skeletons help you think about the key variables that need to be stored / input / output. For example, we could have implemented def surface_area_cylinder(height, radius, circumference). But, a skeleton would likely help us recognize that circumference is redundant if we are given the radius.
Object-oriented design involves two steps: Identifying the elements of the state to store and identifying the actions (which are the methods) to implement.
The Qubit holds the state of a single qubit. As you know, a single qubit has two values, alpha and beta.
Along with the state, we implement a number of methods. First, we need constructor to initialize the state to some default value (|0>).
__init__(self): # constructor to initialize values
Next, we need to implement any setters / getters that are not yet implemented. For any values we want to provide the programmer, instead of making them public, we provide the setter / getter. This is an object-oriented programming convention that makes it easier to make changes to your implementation down the road - change the variable name, the variable type, etc. You only need to make sure that a conversion is provided in the method to support those who wanted direct access.
setvalue(self,v) # accepts a string (bra-ket notation) or list of floats (vector) # to set qubit state # strings are limited to |0> and |1>
getvaluebraket(self) # return qubit state in bra-ket notation as a string
getvaluevector(self) # return qubit state in vector notation as a list
We will implement a few gates and then a measurement function.
notgate(self) hgate(self) zgate(self) measure(self)
Compare two objects so that you and we can check your calculations in test functionscompare(obj1, obj2)
Submit both files; the autograder should evaluate it.