def pad_matrix(matrix, dim, padding): """ Fills matrix dimensions with zeros or identity. """ if padding == "compsub": return matrix elif padding == "wzeros": zeros = np.zeros([dim, dim]) matrix = scipy_block_diag(matrix, zeros) elif padding == "fulluni": identity = np.eye(dim) matrix = scipy_block_diag(matrix, identity) return matrix
def perform(self, node, inputs, output_storage, params=None): dtype = largest_common_dtype(inputs) if self.sparse: output_storage[0][0] = sp.sparse.block_diag( inputs, self.format, dtype) else: output_storage[0][0] = scipy_block_diag(*inputs).astype(dtype)
def perform(self, node, inputs, output_storage, params=None): dtype = largest_common_dtype(inputs) if self.sparse: output_storage[0][0] = sp.sparse.block_diag( inputs, self.format, dtype ) else: output_storage[0][0] = scipy_block_diag(*inputs).astype(dtype)
def test_block_diag(): C1 = np.ones((2, 2)) C2 = np.ones((3, 3)) * 2 C3 = np.ones((3, 3)) * 3 C = scipy_block_diag(C1, C2, C3) C1 = tt.as_tensor_variable(np.ones((2, 2))) C2 = tt.as_tensor_variable(np.ones((3, 3)) * 2) C3 = tt.as_tensor_variable(np.ones((3, 3)) * 3) assert np.allclose(C, lazy_math.block_diag(C1, C2, C3).eval())
def block_diag(self, *mats): if config.lazy: N = [mat.shape[0] for mat in mats] Nsum = tt.sum(N) res = tt.zeros((Nsum, Nsum), dtype=theano.config.floatX) n = 0 for mat in mats: inds = slice(n, n + mat.shape[0]) res = tt.set_subtensor(res[tuple((inds, inds))], mat) n += mat.shape[0] return res else: return scipy_block_diag(*mats)
def perfect_gate(gates_str: str, index=[0, 1], dims=[2, 2], proj: str = "wzeros"): """ Construct an ideal single or two-qubit gate. Parameters ---------- gates_str: str Identifier of the gate, i.e. "X90p". index : list Indeces of the subspace(s) the gate acts on dims : list Dimension of the subspace(s) proj : str Option for projection in the case of more than two-level qubits. Returns ------- np.array Ideal representation of the gate. """ do_pad_gate = True # TODO index for now unused kron_list = [] # for dim in dims: # kron_list.append(np.eye(dim)) kron_gate = 1 gate_num = 0 # Note that the gates_str has to be explicit for all subspaces # (and ordered) for gate_str in gates_str.split(":"): lvls = dims[gate_num] if gate_str == "Id": gate = Id elif gate_str == "X90p": gate = X90p elif gate_str == "X90m": gate = X90m elif gate_str == "Xp": gate = Xp elif gate_str == "Y90p": gate = Y90p elif gate_str == "Y90m": gate = Y90m elif gate_str == "Yp": gate = Yp elif gate_str == "Z90p": gate = Z90p elif gate_str == "Z90m": gate = Z90m elif gate_str == "Zp": gate = Zp elif gate_str == "CNOT": lvls2 = dims[gate_num + 1] NOT = 1j * perfect_gate("Xp", index, [lvls2], proj) C = perfect_gate("Id", index, [lvls2], proj) gate = scipy_block_diag(C, NOT) # We increase gate_num since CNOT is a two qubit gate for ii in range(2, lvls): pad_matrix(gate, lvls2, proj) gate_num += 1 do_pad_gate = False elif gate_str == "CZ": lvls2 = dims[gate_num + 1] Z = 1j * perfect_gate("Zp", index, [lvls2], proj) C = perfect_gate("Id", index, [lvls2], proj) gate = scipy_block_diag(C, Z) # We increase gate_num since CZ is a two qubit gate for ii in range(2, lvls): pad_matrix(gate, lvls2, proj) gate_num += 1 do_pad_gate = False elif gate_str == "CR": # TODO: Fix the ideal CNOT construction. lvls2 = dims[gate_num + 1] Z = 1j * perfect_gate("Zp", index, [lvls], proj) X = perfect_gate("Xp", index, [lvls2], proj) gate = np.kron(Z, X) gate_num += 1 do_pad_gate = False elif gate_str == "CR90": lvls2 = dims[gate_num + 1] RXp = perfect_gate("X90p", index, [lvls2], proj) RXm = perfect_gate("X90m", index, [lvls2], proj) gate = scipy_block_diag(RXp, RXm) for ii in range(2, lvls): gate = pad_matrix(gate, lvls2, proj) gate_num += 1 do_pad_gate = False elif gate_str == "iSWAP": # TODO make construction of iSWAP work with superoperator too lvls2 = dims[gate_num + 1] if lvls == 2 and lvls2 == 2: gate = iswap elif lvls == 3 and lvls2 == 3: gate = iswap3 gate_num += 1 do_pad_gate = False else: print("gate_str must be one of the basic 90 or 180 degree gates.") print( "'Id','X90p','X90m','Xp','Y90p',", "'Y90m','Yp','Z90p','Z90m','Zp', 'CNOT'", ) return None if do_pad_gate: if proj == "compsub": pass elif proj == "wzeros": zeros = np.zeros([lvls - 2, lvls - 2]) gate = scipy_block_diag(gate, zeros) elif proj == "fulluni": identity = np.eye(lvls - 2) gate = scipy_block_diag(gate, identity) kron_list.append(gate) gate_num += 1 return np_kron_n(kron_list)
def perfect_gate( # noqa gates_str: str, index=[0, 1], dims=[2, 2], proj: str = "wzeros"): """ Construct an ideal single or two-qubit gate. Parameters ---------- gates_str: str Identifier of the gate, i.e. "RX90p". index : list Indeces of the subspace(s) the gate acts on dims : list Dimension of the subspace(s) proj : str Option for projection in the case of more than two-level qubits. Returns ------- np.array Ideal representation of the gate. """ do_pad_gate = True # TODO index for now unused kron_list = [] # for dim in dims: # kron_list.append(np.eye(dim)) # kron_gate = 1 gate_num = 0 # Note that the gates_str has to be explicit for all subspaces # (and ordered) for gate_str in gates_str.split(":"): lvls = dims[gate_num] if gate_str == "Id": gate = Id elif gate_str == "RX90p": gate = RX90p elif gate_str == "RX90m": gate = RX90m elif gate_str == "RXp": gate = RXp elif gate_str == "RY90p": gate = RY90p elif gate_str == "RY90m": gate = RY90m elif gate_str == "RYp": gate = RYp elif gate_str == "RZ90p": gate = RZ90p elif gate_str == "RZ90m": gate = RZ90m elif gate_str == "RZp": gate = RZp elif gate_str == "CNOT": raise NotImplementedError( "A correct implementation of perfect CNOT is pending, use CRXp now" ) elif gate_str == "CRXp": # TODO Should this be CNOT? lvls2 = dims[gate_num + 1] NOT = 1j * perfect_gate("RXp", index, [lvls2], proj) C = perfect_gate("Id", index, [lvls2], proj) gate = scipy_block_diag(C, NOT) # We increase gate_num since CNOT is a two qubit gate for ii in range(2, lvls): gate = pad_matrix(gate, lvls2, proj) gate_num += 1 do_pad_gate = False elif gate_str == "CRZp": lvls2 = dims[gate_num + 1] Z = 1j * perfect_gate("RZp", index, [lvls2], proj) C = perfect_gate("Id", index, [lvls2], proj) gate = scipy_block_diag(C, Z) # We increase gate_num since CRZp is a two qubit gate for ii in range(2, lvls): gate = pad_matrix(gate, lvls2, proj) gate_num += 1 do_pad_gate = False elif gate_str == "CR": # TODO: Fix the ideal CNOT construction. lvls2 = dims[gate_num + 1] Z = 1j * perfect_gate("RZp", index, [lvls], proj) X = perfect_gate("RXp", index, [lvls2], proj) gate = np.kron(Z, X) gate_num += 1 do_pad_gate = False elif gate_str == "CR90": lvls2 = dims[gate_num + 1] RXp_temp = perfect_gate("RX90p", index, [lvls2], proj) RXm_temp = perfect_gate("RX90m", index, [lvls2], proj) gate = scipy_block_diag(RXp_temp, RXm_temp) for ii in range(2, lvls): gate = pad_matrix(gate, lvls2, proj) gate_num += 1 do_pad_gate = False elif gate_str == "iSWAP": # TODO make construction of iSWAP work with superoperator too lvls2 = dims[gate_num + 1] if lvls == 2 and lvls2 == 2: gate = iswap elif lvls == 3 and lvls2 == 3: gate = iswap3 gate_num += 1 do_pad_gate = False else: raise KeyError( "gate_str must be one of the basic 90 or 180 degree gates: 'Id','RX90p','RX90m','RXp','RY90p','RY90m','RYp','RZ90p','RZ90m','RZp', 'CNOT', CRXp, CRZp, CR, CR90, iSWAP" ) if do_pad_gate: if proj == "compsub": pass elif proj == "wzeros": zeros = np.zeros([lvls - 2, lvls - 2]) gate = scipy_block_diag(gate, zeros) elif proj == "fulluni": identity = np.eye(lvls - 2) gate = scipy_block_diag(gate, identity) else: raise KeyError("proj should be wzeros, compsub or fulluni") kron_list.append(gate) gate_num += 1 return np_kron_n(kron_list)