示例#1
0
def test_measurement_density_matrix(backend):
    from qibo.tests.test_measurement_gate import assert_result
    state = np.zeros(4)
    state[2] = 1
    rho = np.outer(state, state.conj())
    mgate = gates.M(0, 1)
    mgate.density_matrix = True
    result = mgate(K.cast(rho), nshots=100)

    target_binary_samples = np.zeros((100, 2))
    target_binary_samples[:, 0] = 1
    assert_result(result,
                  decimal_samples=2 * np.ones((100,)),
                  binary_samples=target_binary_samples,
                  decimal_frequencies={2: 100},
                  binary_frequencies={"10": 100})
示例#2
0
def test_maxcut(nqubits, numpy):
    size = 2**nqubits
    ham = np.zeros(shape=(size, size), dtype=np.complex128)
    for i in range(nqubits):
        for j in range(nqubits):
            h = np.eye(1)
            for k in range(nqubits):
                if (k == i) ^ (k == j):
                    h = np.kron(h, matrices.Z)
                else:
                    h = np.kron(h, matrices.I)
            M = np.eye(2**nqubits) - h
            ham += M
    target_ham = K.cast(-ham / 2)
    final_ham = MaxCut(nqubits, numpy=numpy)
    np.testing.assert_allclose(final_ham.matrix, target_ham)
示例#3
0
def test_measurementresult_frequencies(backend):
    import collections
    result = measurements.MeasurementResult((0, 1, 2))
    result.decimal = K.cast([0, 6, 5, 3, 5, 5, 6, 1, 1, 2, 4],
                            dtype='DTYPEINT')
    dfreqs = {0: 1, 1: 2, 2: 1, 3: 1, 4: 1, 5: 3, 6: 2}
    bfreqs = {
        "000": 1,
        "001": 2,
        "010": 1,
        "011": 1,
        "100": 1,
        "101": 3,
        "110": 2
    }
    assert result.frequencies(binary=True) == bfreqs
    assert result.frequencies(binary=False) == dfreqs
示例#4
0
def test_unitary_channel(backend):
    a1 = np.array([[0, 1], [1, 0]])
    a2 = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
    probs = [0.4, 0.3]
    matrices = [((0, ), a1), ((2, 3), a2)]
    initial_state = random_density_matrix(4)
    gate = gates.UnitaryChannel(probs, matrices)
    gate.density_matrix = True
    final_state = gate(K.cast(np.copy(initial_state)))

    eye = np.eye(2)
    ma1 = np.kron(np.kron(a1, eye), np.kron(eye, eye))
    ma2 = np.kron(np.kron(eye, eye), a2)
    target_state = (0.3 * initial_state +
                    0.4 * ma1.dot(initial_state.dot(ma1)) +
                    0.3 * ma2.dot(initial_state.dot(ma2)))
    K.assert_allclose(final_state, target_state)
示例#5
0
def test_reset_channel(backend):
    initial_rho = random_density_matrix(3)
    gate = gates.ResetChannel(0, p0=0.2, p1=0.2)
    gate.density_matrix = True
    final_rho = gate(K.cast(np.copy(initial_rho)))

    dtype = initial_rho.dtype
    collapsed_rho = np.copy(initial_rho).reshape(6 * (2, ))
    collapsed_rho[0, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype)
    collapsed_rho[1, :, :, 0, :, :] = np.zeros(4 * (2, ), dtype=dtype)
    collapsed_rho[1, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype)
    collapsed_rho = collapsed_rho.reshape((8, 8))
    collapsed_rho /= np.trace(collapsed_rho)
    mx = np.kron(np.array([[0, 1], [1, 0]]), np.eye(4))
    flipped_rho = mx.dot(collapsed_rho.dot(mx))
    target_rho = 0.6 * initial_rho + 0.2 * (collapsed_rho + flipped_rho)
    K.assert_allclose(final_rho, target_rho)
示例#6
0
def test_entropy_numerical(backend):
    """Check that entropy calculation does not fail for tiny eigenvalues."""
    original_backend = qibo.get_backend()
    qibo.set_backend(backend)
    from qibo import K
    eigvals = np.array([
        -1e-10, -1e-15, -2e-17, -1e-18, -5e-60, 1e-48, 4e-32, 5e-14, 1e-14,
        9.9e-13, 9e-13, 5e-13, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9, 1e-7, 1, 4, 10
    ])
    rho = K.cast(np.diag(eigvals))
    callback = callbacks.EntanglementEntropy()
    result = callback.entropy(rho)

    mask = eigvals > 0
    target = -(eigvals[mask] * np.log2(eigvals[mask])).sum()

    np.testing.assert_allclose(result, target)
    qibo.set_backend(original_backend)
示例#7
0
def test_maxcut(nqubits, dense, calcterms):
    size = 2**nqubits
    ham = np.zeros(shape=(size, size), dtype=np.complex128)
    for i in range(nqubits):
        for j in range(nqubits):
            h = np.eye(1)
            for k in range(nqubits):
                if (k == i) ^ (k == j):
                    h = np.kron(h, matrices.Z)
                else:
                    h = np.kron(h, matrices.I)
            M = np.eye(2**nqubits) - h
            ham += M
    target_ham = K.cast(-ham / 2)
    final_ham = hamiltonians.MaxCut(nqubits, dense)
    if (not dense) and calcterms:
        _ = final_ham.terms
    K.assert_allclose(final_ham.matrix, target_ham)
示例#8
0
文件: gates.py 项目: qiboteam/qibo
    def cache(self):
        if self._cache is None:
            cache = K.create_gate_cache(self)

            qubits = sorted(self.nqubits - q - 1 for q in self.target_qubits)
            cache.qubits_tensor = K.cast(qubits +
                                         [q + self.nqubits for q in qubits],
                                         dtype="int32")
            cache.target_qubits_dm = self.qubits + tuple(q + self.nqubits
                                                         for q in self.qubits)

            if not K.is_custom:
                cache.calculation_cache = K.create_einsum_cache(
                    cache.target_qubits_dm, 2 * self.nqubits)

            self._cache = cache

        return self._cache
示例#9
0
def test_entropy_random_state(backend):
    """Check that entropy calculation agrees with numpy."""
    # Generate a random positive and hermitian density matrix
    rho = np.random.random((8, 8)) + 1j * np.random.random((8, 8))
    rho = rho + rho.conj().T
    _, u = np.linalg.eigh(rho)
    s = 5 * np.random.random(8)
    s = s / s.sum()
    rho = u.dot(np.diag(s)).dot(u.conj().T)

    callback = callbacks.EntanglementEntropy(compute_spectrum=True)
    result = callback.entropy(K.cast(rho))
    target = - (s * np.log2(s)).sum()
    K.assert_allclose(result, target)

    ref_eigvals = np.linalg.eigvalsh(rho)
    masked_eigvals = ref_eigvals[np.where(ref_eigvals > EIGVAL_CUTOFF)]
    ref_spectrum = - np.log(masked_eigvals)
    K.assert_allclose(callback.spectrum[0], ref_spectrum)
def test_measurement_result_parameters_random(backend, accelerators):
    test_device = K.cpu_devices[0] if accelerators else K.default_device
    initial_state = random_state(4)
    set_device_seed(123, accelerators)
    c = models.Circuit(4, accelerators)
    output = c.add(gates.M(1, collapse=True))
    c.add(gates.RY(0, theta=np.pi * output / 5))
    c.add(gates.RX(2, theta=np.pi * output / 4))
    result = c(initial_state=np.copy(initial_state))
    assert len(output.frequencies()) == 1

    set_device_seed(123, accelerators)
    with K.device(test_device):
        collapse = gates.M(1, collapse=True)
        target_state = collapse(K.cast(np.copy(initial_state)))
        if int(collapse.result.outcome()):
            target_state = gates.RY(0, theta=np.pi / 5)(target_state)
            target_state = gates.RX(2, theta=np.pi / 4)(target_state)
    K.assert_allclose(result, target_state)
def test_measurement_collapse_density_matrix(backend, nqubits, targets):
    initial_rho = random_density_matrix(nqubits)
    gate = gates.M(*targets, collapse=True)
    gate.density_matrix = True
    final_rho = gate(K.cast(np.copy(initial_rho)), nshots=1)
    results = gate.result.binary[0]
    target_rho = np.reshape(initial_rho, 2 * nqubits * (2, ))
    for q, r in zip(targets, results):
        r = int(r)
        slicer = 2 * nqubits * [slice(None)]
        slicer[q], slicer[q + nqubits] = 1 - r, 1 - r
        target_rho[tuple(slicer)] = 0
        slicer[q], slicer[q + nqubits] = r, 1 - r
        target_rho[tuple(slicer)] = 0
        slicer[q], slicer[q + nqubits] = 1 - r, r
        target_rho[tuple(slicer)] = 0
    target_rho = np.reshape(target_rho, initial_rho.shape)
    target_rho = target_rho / np.trace(target_rho)
    K.assert_allclose(final_rho, target_rho)
def test_measurement_result_parameters_multiple_qubits(backend):
    initial_state = random_state(4)
    K.set_seed(123)
    c = models.Circuit(4)
    output = c.add(gates.M(0, 1, 2, collapse=True))
    c.add(gates.RY(1, theta=np.pi * output[0] / 5))
    c.add(gates.RX(3, theta=np.pi * output[2] / 3))
    result = c(initial_state=np.copy(initial_state))

    K.set_seed(123)
    collapse = gates.M(0, 1, 2, collapse=True)
    target_state = collapse(K.cast(np.copy(initial_state)))
    # not including in coverage because outcomes are probabilistic and may
    # not occur for the CI run
    if int(collapse.result.outcome(0)):  # pragma: no cover
        target_state = gates.RY(1, theta=np.pi / 5)(target_state)
    if int(collapse.result.outcome(2)):  # pragma: no cover
        target_state = gates.RX(3, theta=np.pi / 3)(target_state)
    K.assert_allclose(result, target_state)
示例#13
0
def test_measurementresult_apply_bitflips_random_samples_asymmetric(backend):
    qubits = tuple(range(4))
    samples = np.random.randint(0, 2, (20, 4))
    result = measurements.MeasurementResult(qubits)
    result.binary = K.cast(np.copy(samples))
    p1_map = {0: 0.2, 1: 0.0, 2: 0.0, 3: 0.1}
    K.set_seed(123)
    noisy_result = result.apply_bitflips(p0=0.2, p1=p1_map)

    p0 = 0.2 * np.ones(4)
    p1 = np.array([0.2, 0.0, 0.0, 0.1])
    K.set_seed(123)
    sprobs = K.to_numpy(K.random_uniform(samples.shape))
    target_samples = np.copy(samples).ravel()
    ids = (np.where(target_samples == 0)[0], np.where(target_samples == 1)[0])
    target_samples[ids[0]] = samples.ravel()[ids[0]] + (sprobs < p0).ravel()[ids[0]]
    target_samples[ids[1]] = samples.ravel()[ids[1]] - (sprobs < p1).ravel()[ids[1]]
    target_samples = target_samples.reshape(samples.shape)
    K.assert_allclose(noisy_result.samples(), target_samples)
示例#14
0
def test_symbolic_hamiltonian_state_ev(backend, nqubits, normalize, calcterms,
                                       calcdense):
    local_ham = hamiltonians.SymbolicHamiltonian(symbolic_tfim(nqubits,
                                                               h=1.0)) + 2
    if calcterms:
        _ = local_ham.terms
    if calcdense:
        _ = local_ham.dense
    dense_ham = hamiltonians.TFIM(nqubits, h=1.0) + 2

    state = K.cast(random_complex((2**nqubits, )))
    local_ev = local_ham.expectation(state, normalize)
    target_ev = dense_ham.expectation(state, normalize)
    K.assert_allclose(local_ev, target_ev)

    state = random_complex((2**nqubits, ))
    local_ev = local_ham.expectation(state, normalize)
    target_ev = dense_ham.expectation(state, normalize)
    K.assert_allclose(local_ev, target_ev)
示例#15
0
def apply_gates(gatelist, nqubits=None, initial_state=None):
    from qibo import K
    if initial_state is None:
        state = K.qnp.zeros(2 ** nqubits)
        state[0] = 1
    elif isinstance(initial_state, np.ndarray):
        state = np.copy(initial_state)
        if nqubits is None:
            nqubits = int(np.log2(len(state)))
        else: # pragma: no cover
            assert nqubits == int(np.log2(len(state)))
    else: # pragma: no cover
        raise_error(TypeError, "Invalid initial state type {}."
                               "".format(type(initial_state)))

    state = K.cast(state)
    for gate in gatelist:
        state = gate(state)
    return state
示例#16
0
def test_trotter_hamiltonian_matmul(nqubits, normalize):
    """Test Trotter Hamiltonian expectation value."""
    local_ham = hamiltonians.TFIM(nqubits, h=1.0, dense=False)
    dense_ham = hamiltonians.TFIM(nqubits, h=1.0)

    state = K.cast(random_complex((2 ** nqubits,)))
    trotter_ev = local_ham.expectation(state, normalize)
    target_ev = dense_ham.expectation(state, normalize)
    K.assert_allclose(trotter_ev, target_ev)

    state = random_complex((2 ** nqubits,))
    trotter_ev = local_ham.expectation(state, normalize)
    target_ev = dense_ham.expectation(state, normalize)
    K.assert_allclose(trotter_ev, target_ev)

    from qibo.core.states import VectorState
    state = VectorState.from_tensor(state)
    trotter_matmul = local_ham @ state
    target_matmul = dense_ham @ state
    K.assert_allclose(trotter_matmul, target_matmul)
示例#17
0
def test_thermal_relaxation_channel(backend, t1, t2, time, excpop):
    """Check ``gates.ThermalRelaxationChannel`` on a 3-qubit random density matrix."""
    initial_rho = random_density_matrix(3)
    gate = gates.ThermalRelaxationChannel(0,
                                          t1,
                                          t2,
                                          time=time,
                                          excited_population=excpop)
    gate.density_matrix = True
    final_rho = gate(K.cast(np.copy(initial_rho)))  # pylint: disable=E1102

    exp, p0, p1 = gate.calculate_probabilities(t1, t2, time, excpop)
    if t2 > t1:
        matrix = np.diag([1 - p1, p0, p1, 1 - p0])
        matrix[0, -1], matrix[-1, 0] = exp, exp
        matrix = matrix.reshape(4 * (2, ))
        # Apply matrix using Eq. (3.28) from arXiv:1111.6950
        target_rho = np.copy(initial_rho).reshape(6 * (2, ))
        target_rho = np.einsum("abcd,aJKcjk->bJKdjk", matrix, target_rho)
        target_rho = target_rho.reshape(initial_rho.shape)
    else:
        pz = exp
        pi = 1 - pz - p0 - p1
        dtype = initial_rho.dtype
        collapsed_rho = np.copy(initial_rho).reshape(6 * (2, ))
        collapsed_rho[0, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype)
        collapsed_rho[1, :, :, 0, :, :] = np.zeros(4 * (2, ), dtype=dtype)
        collapsed_rho[1, :, :, 1, :, :] = np.zeros(4 * (2, ), dtype=dtype)
        collapsed_rho = collapsed_rho.reshape((8, 8))
        collapsed_rho /= np.trace(collapsed_rho)
        mx = np.kron(np.array([[0, 1], [1, 0]]), np.eye(4))
        mz = np.kron(np.array([[1, 0], [0, -1]]), np.eye(4))
        z_rho = mz.dot(initial_rho.dot(mz))
        flipped_rho = mx.dot(collapsed_rho.dot(mx))
        target_rho = (pi * initial_rho + pz * z_rho + p0 * collapsed_rho +
                      p1 * flipped_rho)
    K.assert_allclose(final_rho, target_rho)
    # Try to apply to state vector if t1 < t2
    if t1 < t2:
        with pytest.raises(ValueError):
            gate._state_vector_call(initial_rho)  # pylint: disable=no-member
def test_post_measurement_bitflips_on_circuit_result(backend):
    """Check bitflip errors on ``CircuitResult`` objects."""
    thetas = np.random.random(4)
    c = models.Circuit(4)
    c.add((gates.RX(i, theta=t) for i, t in enumerate(thetas)))
    c.add(gates.M(0, 1, register_name="a"))
    c.add(gates.M(3, register_name="b"))
    result = c(nshots=30)
    samples = result.samples()
    K.set_seed(123)
    noisy_result = result.copy().apply_bitflips({0: 0.2, 1: 0.4, 3: 0.3})
    noisy_samples = noisy_result.samples(binary=True)
    register_samples = noisy_result.samples(binary=True, registers=True)

    K.set_seed(123)
    sprobs = K.to_numpy(K.random_uniform(samples.shape))
    flipper = K.cast(sprobs < np.array([0.2, 0.4, 0.3]), dtype=samples.dtype)
    target_samples = (samples + flipper) % 2
    K.assert_allclose(noisy_samples, target_samples)
    # Check register samples
    K.assert_allclose(register_samples["a"], target_samples[:, :2])
    K.assert_allclose(register_samples["b"], target_samples[:, 2:])
示例#19
0
def test_measurementregistersresult_frequencies(backend):
    probs = np.random.random(16)
    probs = K.cast(probs / np.sum(probs), dtype='DTYPE')
    result = measurements.MeasurementResult((0, 1, 2, 3),
                                            probs,
                                            nshots=1000000)
    frequencies = result.frequencies()
    qubits = {"a": (0, 1), "b": (2, 3)}
    result = measurements.MeasurementRegistersResult(qubits, result)
    register_frequencies = result.frequencies(registers=True)
    assert register_frequencies.keys() == qubits.keys()
    rkeys = ["00", "01", "10", "11"]
    target_frequencies_a = {
        k: sum(frequencies[f"{k}{l}"] for l in rkeys)
        for k in rkeys
    }
    target_frequencies_b = {
        k: sum(frequencies[f"{l}{k}"] for l in rkeys)
        for k in rkeys
    }
    assert register_frequencies["a"] == target_frequencies_a
    assert register_frequencies["b"] == target_frequencies_b
示例#20
0
def test_apply_pauli_gate(nqubits, target, gate, compile):
    """Check ``apply_x``, ``apply_y`` and ``apply_z`` kernels."""
    matrices = {
        "x": np.array([[0, 1], [1, 0]], dtype=np.complex128),
        "y": np.array([[0, -1j], [1j, 0]], dtype=np.complex128),
        "z": np.array([[1, 0], [0, -1]], dtype=np.complex128)
    }
    state = random_complex((2**nqubits, ))
    target_state = K.cast(state, dtype=state.dtype)
    qubits = qubits_tensor(nqubits, [target])
    target_state = K.op.apply_gate(state, matrices[gate], qubits, nqubits,
                                   target, get_threads())

    def apply_operator(state):
        qubits = qubits_tensor(nqubits, [target])
        return getattr(K.op, "apply_{}".format(gate))(state, qubits, nqubits,
                                                      target, get_threads())

    if compile:
        apply_operator = K.compile(apply_operator)
    state = apply_operator(state)

    np.testing.assert_allclose(target_state.numpy(), state.numpy())
示例#21
0
def test_apply_gate_cx(nqubits, compile):
    """Check ``K.op.apply_gate`` for multiply-controlled X gates."""
    state = random_complex((2**nqubits, ))

    target_state = np.array(state)
    gate = np.eye(2**nqubits, dtype=target_state.dtype)
    gate[-2, -2], gate[-2, -1] = 0, 1
    gate[-1, -2], gate[-1, -1] = 1, 0
    target_state = np.dot(gate, target_state)

    xgate = K.cast([[0, 1], [1, 0]], dtype=state.dtype)
    controls = list(range(nqubits - 1))

    def apply_operator(state):
        qubits = qubits_tensor(nqubits, [nqubits - 1], controls)
        return K.op.apply_gate(state, xgate, qubits, nqubits, nqubits - 1,
                               get_threads())

    if compile:
        apply_operator = K.compile(apply_operator)
    state = apply_operator(state)

    np.testing.assert_allclose(target_state, state)
示例#22
0
def test_swap_pieces(nqubits):
    state = random_complex((2**nqubits, ))
    target_state = K.cast(np.copy(state.numpy()), dtype=state.dtype)
    shape = (2, int(state.shape[0]) // 2)

    for _ in range(10):
        global_qubit = np.random.randint(0, nqubits)
        local_qubit = np.random.randint(0, nqubits)
        while local_qubit == global_qubit:
            local_qubit = np.random.randint(0, nqubits)

        transpose_order = ([global_qubit] + list(range(global_qubit)) +
                           list(range(global_qubit + 1, nqubits)))

        qubits_t = qubits_tensor(nqubits, [global_qubit, local_qubit])
        target_state = K.op.apply_swap(target_state, qubits_t,
                                       nqubits, global_qubit, local_qubit,
                                       get_threads())
        target_state = K.reshape(target_state, nqubits * (2, ))
        target_state = K.transpose(target_state, transpose_order)
        target_state = K.reshape(target_state, shape)

        state = K.reshape(state, nqubits * (2, ))
        state = K.transpose(state, transpose_order)
        state = K.reshape(state, shape)
        piece0, piece1 = state[0], state[1]
        if K.gpu_devices:  # pragma: no cover
            # case not tested by GitHub workflows because it requires GPU
            check_unimplemented_error(K.op.swap_pieces, piece0, piece1,
                                      local_qubit - 1, nqubits - 1,
                                      get_threads())
        else:
            K.op.swap_pieces(piece0, piece1,
                             local_qubit - int(global_qubit < local_qubit),
                             nqubits - 1, get_threads())
            np.testing.assert_allclose(target_state[0], piece0.numpy())
            np.testing.assert_allclose(target_state[1], piece1.numpy())
示例#23
0
def test_swap_pieces_zero_global(nqubits):
    state = random_complex((2**nqubits, ))
    target_state = K.cast(np.copy(state.numpy()))
    shape = (2, int(state.shape[0]) // 2)
    state = K.reshape(state, shape)

    for _ in range(10):
        local = np.random.randint(1, nqubits)

        qubits_t = qubits_tensor(nqubits, [0, local])
        target_state = K.op.apply_swap(target_state, qubits_t, nqubits, 0,
                                       local, get_threads())
        target_state = K.reshape(target_state, shape)

        piece0, piece1 = state[0], state[1]
        if K.gpu_devices:  # pragma: no cover
            # case not tested by GitHub workflows because it requires GPU
            check_unimplemented_error(K.op.swap_pieces, piece0, piece1,
                                      local - 1, nqubits - 1, get_threads())
        else:
            K.op.swap_pieces(piece0, piece1, local - 1, nqubits - 1,
                             get_threads())
            np.testing.assert_allclose(target_state[0], piece0.numpy())
            np.testing.assert_allclose(target_state[1], piece1.numpy())
示例#24
0
文件: gates.py 项目: mlazzarin/qibo
 def _state_vector_call(self, state):
     shape = tuple(state.shape)
     _state = K.qnp.reshape(K.qnp.cast(self.coefficients), shape)
     return K.cast(_state, dtype="DTYPECPX")
示例#25
0
文件: gates.py 项目: mlazzarin/qibo
 def custom_op_matrix(self):
     if self._custom_op_matrix is None:
         self._custom_op_matrix = K.cast(K.qnp.exp(1j * self.parameters))
     return self._custom_op_matrix
示例#26
0
文件: gates.py 项目: mlazzarin/qibo
 def _construct_unitary(self):
     matrix = K.qnp.diag(
         [1 - self.preset1, self.exp_t2, self.exp_t2, 1 - self.preset0])
     matrix[0, -1] = self.preset1
     matrix[-1, 0] = self.preset0
     return K.cast(matrix)
示例#27
0
文件: gates.py 项目: NourO93/qibo
 def construct_unitary(self):
     unitary = self.parameters
     rank = int(math.log2(int(unitary.shape[0])))
     matrix = K.copy(K.cast(unitary))
     return matrix
示例#28
0
文件: gates.py 项目: NourO93/qibo
 def construct_unitary(self):
     return K.cast([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
示例#29
0
文件: gates.py 项目: NourO93/qibo
 def construct_unitary(self):
     t = K.cast(self.parameters)
     phase = K.exp(1j * t)
     return K.diag([1, phase])
示例#30
0
文件: gates.py 项目: NourO93/qibo
 def construct_unitary(self):
     t = K.cast(self.parameters)
     phase = K.exp(1j * t / 2.0)[K.newaxis]
     diag = K.concatenate([K.conj(phase), phase], axis=0)
     return K.diag(diag)