Goals for this homework

  • Add Superposition, phase, and 2-qubit operations to your qubit
  • Increase familiarity with Java

You are expected to complete this assignment individually. If you need help, you are invited to come to office hours and/or ask questions on Canvas. Clarification questions about the assignments may be asked publicly. Once you have specific bugs related to your code, make the posts private.

In this homework, you'll add to the qubit we created.

You should submit several files for this assignment ( Qubit.java, TestQubit.java, tests.txt Makefile). You will submit your work in a zip file to Gradescope. More detailed submission instructions will come later.

Error Handling

Error handling capabilities vary by language, and what you want to do in an error varies by the situation. When an error occurs in a function, the question becomes, what should you do, and how do you notify the caller that an error occurred?

In Java, there is a construct for this. We'll use this when calling methods that use it but, right now, we won't implement them ourselves. This is an exercise because if you write a method, and it's used in a variety of different circumstances, it is bad programming practice to determine within the function what will be done. For example, one program might want to exit, whereas another might want to notify the user that there was bad input and to try again.

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 function.

  System.out.println("error: too many widgets for the number of grommets");
  System.out.println("error: need ten boondoggles, but only have + num_bds");

Sometimes, these lines will be followed by System.exit(1); This immediately exits the program and returns a code. If you were writing a large program, you might assign a different code to each type of error that would result in an exit.

Set Up

Make sure you add to your Qubit class to make a working skeleton. You are already starting out with a Qubit class, so all you need to do is
  • Step 1: In Qubit.java, add in the new method declarations. In the method body, print the fact that it is not yet implemented and return with the right type. For example:
    public float surface_area_cylinder(float height, float radius)
    {
    	Console.WriteLine("surface_area_cylinder not yet implemented");
    	return 0.0;
    }
    
  • Step 2: Add a test method and a call to the test method in the main method. For each method, put in a single call. For example:
    public static void Main(string[] args)
    {
    	float fval;
    
    	fval = test_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.

Qubit Class

You are adding three pieces of functionality: Superposition, measurement, phase, and multiple qubit operations.

Superposition: This means that the value can be not only 0 or 1, but somewhere in between. You need to store the state such that a) you can perform accurate measurements on it and b) it can be used for single and multiple qubit operations. I am not specifying how you store the state - however, it will need to store all the pertinent information. Assume that when someone enters a float, it is the probability, between 0 and 1, inclusive, of measuring a 1. They can also enter a negative number, which would indicate a negative phase.

Measurement: You implement a simple measurement method that measures whether it is 0 or 1, and the measurement outcomes (over time) need to match the desired probability (within the constraints of the random number generators in classical computers).

Phase: You need to store whether the phase is positive or negative. This does not affect the measurement, but it affects operations.

New Gates: You need to implement the H gate, swap gate, and C-NOT gates. You only need to handle limited superposition, as specified below.

Adjust and add methods as specified below:
    • public Qubit()
      // initialize to zero, positive phase
    • public Qubit(float v)
      // check sign of float for phase
      // allow any number between -1 and 1, inclusive
    • public Qubit(String v)
      // set phase to positive
    • public void setValue(float v)
      // inspect sign of float for phase
    • public void setValue(String v)
      // set phase to positive
    • public float getValue()
      // return probability of measuring 1 multiplied by the phase
    • public void setPhase(int phase)
      // assume -1 for negative phase, 1 for positive phase
    • public int getPhase(int phase)
      // return -1 for negative phase, 1 for positive phase
    • public void not()
      // make sure your implementation works for superposition and phase
      // for now, we will assume that not does not affect the phase
    • public void hgate()
      // support the following inputs: 0 with positive phase, 1 with positive phase,
      // superposition of 50\%, superposition of 50\% with negative phase
    • public void swap(Qubit q2)
      // make sure your implementation works for superposition and phase
      // Phase is swapped just as the rest of the state is swapped.
    • public void cnot(Qubit q2)
      // support only 0 and 1 inputs, positive phase
    • public int measureValue()
      // this performs measurement to determine whether the ``color'' is white or
      // black, or the value is 0 or 1. This both outputs the measured value
      // and sets the value in the Qubit to that result, collapsing any superposition
      // that might have been present.
    • public String toBraKet()
      This method will produce a string that prints out the value in bra-ket
      notation. Leave no space between |, value, and >, but put a space before
      and after the + or - of the phase. Always report the phase on the second
      bit. Remember that bra-ket notation does not use the probability itself -
      it uses the square root of the probability. You may use mathematics functions.
      Have it print out no more than 2 digits to the right of the decimal point
      (e.g. 0.33), and print out a 0 to the left of the decimal point. If the
      rightmost digit is 0, do not print it out (e.g. 0.5). If the probability is
      0 / 1, then print out only one term, and drop the 1 in front of it (e.g. |0>).

Testing



For testing Point, the general test line will look like this:
java TestQubit start_state expected_end_state test# inputs expected_ret_val

We will keep the tests from last week. Make sure you add more test cases to test for the new functinoality you added. In addition, we will have the following new tests:
  • setPhase: java TestQubit ss ees 5 i
    Example: java TestQubit -0.5 0.5 5 1
  • getPhase: java TestQubit ss ees 6 i
    Example: java TestQubit -0.75 -0.75 6 -1
  • hgate: java TestQubit ss ees 7
    Example: java TestQubit 1 -0.5 7
  • swap: java TestQubit ss1 ees1 8 ss2 ees2
    java TestQubit -0.3 0.6 8 0.6 -0.3
  • cnot: java TestQubit ssc eesc 9 sst eest
    java TestQubit 1 1 9 0 1
  • measure: java TestQubit ss ees 10
    java TestQubit -0.5 0.5 10
    // note: This doesn't actually have an expected return value - this doesn't fit the
    // mold because we now have probilistic outcomes. You'll need to do many trials, and
    // then see if the average value matches the expected value.
  • toBraKet: java TestQubit ss ees 11
    java TestQubit 0.5 0.5 11
    // note: you need to print out the string and check it visually

Submit