04 Jun 2015
C#, F#, Maths, QSharp, Quantum Computing
The quantum Z gate is represented by the Pauli-Z matrix. It can be used to perform Z operations on a single qubit.
In QSharp, the Z gate implementation is provided by the PauliZGate type. Like all QSharp gate implementations, this type inherits from the Matrix type, which describes a mathematical matrix structure used in all gate operations. The mathematics of the PauliZGate are discussed further in the Z command documentation.
Consider the following C# code, which demonstrates various PauliZGate type functionality:
public static void Main(string[] Arguments) { // Construct a register with 2 random qubits Register oRegister = new Register(2); // Always check that we start off with a valid register if (oRegister.IsNormalised() == false) { oRegister.Normalise(); } // Write the initial state to the console WriteQubits(oRegister); WriteStateVector(oRegister); Console.WriteLine(); // Construct a new Pauli Z gate PauliZGate oPauliZGate = new PauliZGate(); // What does the Pauli Z gate look like? Console.WriteLine("Pauli Z:"); Console.WriteLine(oPauliZGate); // Apply the gate to qubit 0 Console.WriteLine(); Console.WriteLine("Z(0);"); oRegister.StateVector = oPauliZGate.ApplyTo(oRegister); // Write the state to the console WriteStateVector(oRegister); // Apply the gate to qubit 0 - note that this is a reversible operation Console.WriteLine(); Console.WriteLine("Z(0);"); oRegister.StateVector = oPauliZGate.ApplyTo(oRegister); // Write the state to the console WriteStateVector(oRegister); // Now apply the gate to qubit 1 (this is also reversible operation) Console.WriteLine(); Console.WriteLine("Z(1);"); oRegister.StateVector = oPauliZGate.ApplyTo(1, oRegister); WriteStateVector(oRegister); } private static void WriteQubits(Register Register) { Console.WriteLine(); Console.WriteLine("Qubits:"); for (int i = 0; i < Register.Qubits.Count; i++) { Console.Write("({0}|0> + {1}|1>)", Register.Qubits[i].AlphaLabel, Register.Qubits[i].BetaLabel); if (i < (Register.Qubits.Count - 1)) { Console.Write(" (x) "); } } Console.WriteLine(); } private static void WriteStateVector(Register Register) { Console.WriteLine(); Console.WriteLine("State Vector:"); Console.Write("|v> = ("); for (int i = 0; i < Register.StateVector.Length; i++) { // Use the overload to control the output Console.Write(Register.StateVector[i].ToString(true, false)); if (i < (Register.StateVector.Length - 1)) { Console.Write(" + "); } } Console.WriteLine(")"); }
And again, this time in F#:
type Program() = [<EntryPoint>] static let main argv = // Construct a register with 2 random qubits let oRegister = new Register(2) // Always check that we start off with a valid register if oRegister.IsNormalised() = false then oRegister.Normalise() // Write the initial state to the console Program.WriteQubits(oRegister) Program.WriteStateVector(oRegister) printfn "" // Construct a new Pauli Z gate let oPauliZGate = new PauliZGate(); // What does the Pauli Z gate look like? let sPauliZ = oPauliZGate.ToString() printfn "Pauli Z:" printfn "%s" sPauliZ // Apply the gate to qubit 0 printfn "" printfn "Z(0);" oRegister.StateVector <- oPauliZGate.ApplyTo(oRegister); // Write the state to the console Program.WriteStateVector(oRegister); // Apply the gate to qubit 0 - note that this is a reversible operation printfn "" printfn "Z(0);" oRegister.StateVector <- oPauliZGate.ApplyTo(oRegister); // Write the state to the console Program.WriteStateVector(oRegister); // Now apply the gate to qubit 1 (this is also reversible operation) printfn "" printfn "Z(1);" oRegister.StateVector <- oPauliZGate.ApplyTo(1, oRegister); Program.WriteStateVector(oRegister); 0 // return an integer exit code static member WriteQubits(register: Register) = printfn "" printfn "Qubits:" for i in 0 .. (register.Qubits.Length - 1) do let oQubit = register.Qubits.[i] printf "(%s|0> + %s|1>)" oQubit.AlphaLabel oQubit.BetaLabel if i < (register.Qubits.Length - 1) then printf " (x) " printfn "" static member WriteStateVector(register: Register) = printfn "" printfn "State Vector:" printf "|v> = (" for i in 0 .. (register.StateVector.Length - 1) do // Using the overload to control the output let sState = register.StateVector.[i].ToString(true, true) printf "%s" sState if i < (register.StateVector.Length - 1) then printf " + " printfn ")"
In QSharp, the PauliZGate can only really do one thing: be applied to a state vector.
This small program produces the following output:
State Vector: |v> = (AC|00> + AD|01> + BC|10> + BD|11>) Pauli Z: { {1, 0}, {0,-1} } Z(0); State Vector: |v> = (AC|00> + AD|01> + -BC|10> + -BD|11>) // The qubits in position 0 have been multiplied by 1 and -1 (A mapped to (1 * A) = A, B mapped to (-1 * B) = -B) Z(0); State Vector: |v> = (AC|00> + AD|01> + BC|10> + BD|11>) // The qubits in position 0 have been multiplied by 1 and -1 (A mapped to (1 * A) = A, -B mapped to (-1 * -B) = B) Z(1); State Vector: |v> = (AC|00> + -AD|01> + BC|10> + -BD|11>)// The qubits in position 1 have been multiplied by 1 and -1 (D mapped to (-1 * D) = -D, C mapped to (1 * C) = C)
* Note that coefficient values have not been written back to the console in this example
Here's the same code, however now coefficients are displayed in the console rather than algebraic values:
Qubits: (A|0> + B|1>) (x) (C|0> + D|1>) State Vector: |v> = (0.903|00> + 0.378|01> + 0.187|10> + 0.078|11>) Pauli Z: { {1, 0}, {0,-1} } Z(0); State Vector: |v> = (0.903|00> + 0.378|01> + -0.187|10> + -0.078|11>) Z(0); State Vector: |v> = (0.903|00> + 0.378|01> + 0.187|10> + 0.078|11>) Z(1); State Vector: |v> = (0.903|00> + -0.378|01> + 0.187|10> + -0.078|11>)
In this example, it may be easier to focus just on the single coefficient, rather than tracking two algebraic values per state vector element.
Copyright © 2025 carlbelle.com