def test_linalg(self): A = QuantumGate(array([[0.0, 1.0], [0.0, 0.0]])) B = QuantumGate(array([[0.0, 0.0], [1.0, 0.0]])) self.assertTrue((A.H().matrix() == B.matrix()).all()) X = A + B self.assertTrue((X.matrix() == x_gate().matrix()).all()) self.assertTrue((dot(X, X).matrix() == eye(2)).all())
def function_gate(f, m, k): """Factory method for a gate that implements a classical function. Args: f: A function that takes a sequence of bits of length m and returns another sequence of bits of length k. The bit sequences are represented by the integers they represent in binary: e.g. "00101" would be the integer 5. m: Length of bits for the input to f. k: Length of bits for the output to f. Returns: The resulting gate, Uf, takes as its input a qubit system of length m+k. Call the first m qubits in the system "x" and the last k qubits "y": then the action of Uf on a pure state |x, y> is to map it to |x, f(x) (+) y> where (+) represents bitwise addition mod 2 (equivalent to the XOR operation). It is easily shown that the map |x, y> --> |x, f(x) (+) y> is a bijection, which implies that Uf is a permutation matrix (and is therefore unitary). """ # the gate operates on an (m+k)-qubit system G = QuantumGate(zeros((2**(m+k), 2**(m+k)))) # filter that zeros out all but the last k bits FILTER = (1 << k) - 1 for j in range(G.matrix().shape[1]): y = j & FILTER # y is the last k bits of the jth state x = j >> k # x is the state ignoring the last k bits # The gate maps |x,y> to |x,y + f(x)>, where + is bitwise addition mod 2 i = (x << k) + (y ^ f(x)) G[i,j] = 1. return G