Beispiel #1
0
def evolve_fqe_givens_unrestricted(wfn: Wavefunction,
                                   u: np.ndarray) -> Wavefunction:
    """Evolve a wavefunction by u generated from a 1-body Hamiltonian.

    Args:
        wfn: 2^{n} x 1 vector.
        u: (n x n) unitary matrix.

    Returns:
        New evolved wfn object.
    """
    rotations, diagonal = givens_decomposition_square(u.copy())
    # Iterate through each layer and time evolve by the appropriate
    # fermion operators
    for layer in rotations:
        for givens in layer:
            i, j, theta, phi = givens
            if not np.isclose(phi, 0):
                op = of.FermionOperator(((j, 1), (j, 0)), coefficient=-phi)
                wfn = wfn.time_evolve(1.0, op)
            if not np.isclose(theta, 0):
                op = of.FermionOperator(
                    ((i, 1),
                     (j, 0)), coefficient=-1j * theta) + of.FermionOperator(
                         ((j, 1), (i, 0)), coefficient=1j * theta)
                wfn = wfn.time_evolve(1.0, op)

    # evolve the last diagonal phases
    for idx, final_phase in enumerate(diagonal):
        if not np.isclose(final_phase, 1.0):
            op = of.FermionOperator(((idx, 1), (idx, 0)),
                                    -np.angle(final_phase))
            wfn = wfn.time_evolve(1.0, op)

    return wfn
Beispiel #2
0
def evolve_fqe_givens_sector(wfn: Wavefunction, u: np.ndarray,
                             sector='alpha') -> Wavefunction:
    """Evolve a wavefunction by u generated from a 1-body Hamiltonian.

    Args:
        wfn: FQE Wavefunction on n-orbitals
        u: (n x n) unitary matrix.
        sector: Optional either 'alpha' or 'beta' indicating which sector
                to rotate
    Returns:
        New evolved wfn object.
    """
    if sector == 'alpha':
        sigma = 0
    elif sector == 'beta':
        sigma = 1
    else:
        raise ValueError("Bad section variable.  Either (alpha) or (beta)")

    if not np.isclose(u.shape[0], wfn.norb()):
        raise ValueError(
            "unitary is not specified for the correct number of orbitals")

    rotations, diagonal = givens_decomposition_square(u.copy())
    # Iterate through each layer and time evolve by the appropriate
    # fermion operators
    for layer in rotations:
        for givens in layer:
            i, j, theta, phi = givens
            if not np.isclose(phi, 0):
                op = of.FermionOperator(
                    ((2 * j + sigma, 1), (2 * j + sigma, 0)), coefficient=-phi)
                wfn = wfn.time_evolve(1.0, op)
            if not np.isclose(theta, 0):
                op = of.FermionOperator(((2 * i + sigma, 1),
                                         (2 * j + sigma, 0)),
                                        coefficient=-1j * theta) + \
                     of.FermionOperator(((2 * j + sigma, 1),
                                         (2 * i + sigma, 0)),
                                        coefficient=1j * theta)
                wfn = wfn.time_evolve(1.0, op)

    # evolve the last diagonal phases
    for idx, final_phase in enumerate(diagonal):
        if not np.isclose(final_phase, 1.0):
            op = of.FermionOperator(
                ((2 * idx + sigma, 1), (2 * idx + sigma, 0)),
                -np.angle(final_phase))
            wfn = wfn.time_evolve(1.0, op)

    return wfn
Beispiel #3
0
def evolve_fqe_charge_charge_sector(wfn: Wavefunction,
                                    vij_mat: np.ndarray,
                                    sector='alpha',
                                    time=1) -> Wavefunction:
    r"""Utility for testing evolution of a full 2^{n} wavefunction via

    :math:`exp{-i time * \sum_{i,j}v_{i, j}n_{i, alpha}n_{j, beta}}.`

    Args:
        wfn: fqe_wf with sdim = n
        vij_mat: List[(n x n] matrices n is the spatial orbital rank
        time: evolution time.

    Returns:
        New evolved 2^{2 * n} x 1 vector
    """
    if sector == 'alpha':
        sigma = 0
    elif sector == 'beta':
        sigma = 1
    else:
        raise ValueError("Sector must be alpha or beta.")

    norbs = vij_mat.shape[0]
    for p, q in product(range(norbs), repeat=2):
        if np.isclose(vij_mat[p, q], 0):
            continue
        fop = of.FermionOperator(((2 * p + sigma, 1), (2 * p + sigma, 0),
                                  (2 * q + sigma, 1), (2 * q + sigma, 0)),
                                 coefficient=vij_mat[p, q])
        wfn = wfn.time_evolve(time, fop)
    return wfn
Beispiel #4
0
    def test_evolve_spinful_fermionop(self):
        """
        Make sure the spin-orbital reordering is working by comparing
        time evolution
        """
        wfn = Wavefunction([[2, 0, 2]])
        wfn.set_wfn(strategy='random')
        wfn.normalize()
        cirq_wf = to_cirq(wfn).reshape((-1, 1))

        op_to_apply = FermionOperator()
        for p, q, r, s in product(range(2), repeat=4):
            op = FermionOperator(
                ((2 * p, 1), (2 * q + 1, 1), (2 * r + 1, 0), (2 * s, 0)),
                coefficient=numpy.random.randn())
            op_to_apply += op + hermitian_conjugated(op)

        opmat = get_sparse_operator(op_to_apply, n_qubits=4).toarray()
        dt = 0.765
        new_state_cirq = scipy.linalg.expm(-1j * dt * opmat) @ cirq_wf
        new_state_wfn = from_cirq(new_state_cirq.flatten(), thresh=1.0E-12)
        test_state = wfn.time_evolve(dt, op_to_apply)
        self.assertTrue(
            numpy.allclose(test_state.get_coeff((2, 0)),
                           new_state_wfn.get_coeff((2, 0))))
Beispiel #5
0
def evolve_fqe_diagaonal_coulomb(wfn: Wavefunction, vij_mat: np.ndarray,
                                 time=1) -> Wavefunction:
    r"""Utility for testing evolution of a full 2^{n} wavefunction via

    :math:`exp{-i time * \sum_{i,j, sigma, tau}v_{i, j}n_{i\sigma}n_{j\tau}}.`

    Args:
        wfn: 2^{n} x 1 vector.
        vij_mat: List[(n//2 x n//2)] matrices
        time: evolution time.

    Returns:
        New evolved 2^{n} x 1 vector
    """
    dc_ham = DiagonalCoulomb(vij_mat)
    return wfn.time_evolve(time, dc_ham)
Beispiel #6
0
def evolve_fqe_charge_charge_unrestricted(wfn: Wavefunction,
                                          vij_mat: np.ndarray,
                                          time=1) -> Wavefunction:
    r"""Utility for testing evolution of a full 2^{n} wavefunction via

    :math:`exp{-i time * \sum_{i,j}v_{i, j}n_{i}n_{j}}.`

    Args:
        wfn: fqe_wf with sdim = n
        vij_mat: List[(n x n] matrices
        time: evolution time.

    Returns:
        New evolved 2^{n} x 1 vector
    """
    nso = vij_mat.shape[0]
    for p, q in product(range(nso), repeat=2):
        if np.isclose(vij_mat[p, q], 0):
            continue
        fop = of.FermionOperator(((p, 1), (p, 0), (q, 1), (q, 0)),
                                 coefficient=vij_mat[p, q])
        wfn = wfn.time_evolve(time, fop)
    return wfn