Пример #1
0
def test_daulbasis_init():
    db = DualBasis()
    assert isinstance(db, DualBasis)
    dbe = DualBasisElement(tensor_names=['A'] * 5,
                           tensor_coeffs=[1] * 5,
                           tensor_elements=[(i, i) for i in range(5)])
    db = DualBasis(elements=[dbe])
    assert db[0] == dbe
    assert len(db) == 1
    for tdbe in db:
        assert tdbe == dbe

    db2 = db + dbe
    assert isinstance(db2, DualBasis)
    assert len(db2) == 2

    tdbe = DualBasisElement(tensor_names=['B'] * 5,
                            tensor_coeffs=[1] * 5,
                            tensor_elements=[(i, i) for i in range(5)])
    tdb = DualBasis(elements=[tdbe])
    db3 = db + tdb
    assert isinstance(db3, DualBasis)
    assert len(db3) == 2

    db4 = tdbe + db
    assert len(db4) == 2

    with pytest.raises(TypeError):
        _ = DualBasis(elements=[tdbe, 4])

    with pytest.raises(TypeError):
        db = DualBasis(elements=[tdbe])
        _ = db + 4
Пример #2
0
def test_dual_basis_element():
    de = DualBasisElement()
    de_2 = DualBasisElement()
    db_0 = de + de_2
    assert isinstance(db_0, DualBasis)
    db_1 = db_0 + db_0
    assert isinstance(db_1, DualBasis)

    dim = 2
    opdm = np.random.random((dim, dim))
    opdm = (opdm.T + opdm) / 2
    opdm = Tensor(tensor=opdm, name='opdm')
    rdm = MultiTensor([opdm])

    def generate_dual_basis_element(i, j):
        element = DualBasisElement(tensor_names=["opdm"],
                                   tensor_elements=[(i, j)],
                                   tensor_coeffs=[-1.0],
                                   bias=1 if i == j else 0,
                                   scalar=0)
        return element

    opdm_to_oqdm_map = DualBasis()
    for _, idx in opdm.all_iterator():
        i, j = idx
        opdm_to_oqdm_map += generate_dual_basis_element(i, j)

    rdm.dual_basis = opdm_to_oqdm_map
    A, b, _ = rdm.synthesize_dual_basis()
    Adense = A.todense()
    opdm_flat = opdm.data.reshape((-1, 1))
    oqdm = Adense.dot(opdm_flat)
    test_oqdm = oqdm + b.todense()
    assert np.allclose(test_oqdm.reshape((dim, dim)), np.eye(dim) - opdm.data)
Пример #3
0
def test_dbe_element_add():
    de = DualBasisElement()
    de_2 = DualBasisElement()
    db_0 = de + de_2
    assert isinstance(db_0, DualBasis)
    db_0 = de_2 + de
    assert isinstance(db_0, DualBasis)
    db_1 = db_0 + db_0
    assert isinstance(db_1, DualBasis)

    with pytest.raises(TypeError):
        _ = de + 2
Пример #4
0
def test_dualbasis_element_init():
    dbe = DualBasisElement()
    assert isinstance(dbe, DualBasisElement)

    dbe = DualBasisElement(tensor_names=['A'] * 5,
                           tensor_coeffs=[1] * 5,
                           tensor_elements=[(i, i) for i in range(5)])

    assert dbe.primal_tensors_names == ['A'] * 5
    assert dbe.primal_coeffs == [1] * 5
    assert dbe.primal_elements == [(i, i) for i in range(5)]
    assert dbe.constant_bias == 0
    assert dbe.dual_scalar == 0
Пример #5
0
 def generate_dual_basis_element(i, j):
     element = DualBasisElement(tensor_names=["opdm"],
                                tensor_elements=[(i, j)],
                                tensor_coeffs=[-1.0],
                                bias=1 if i == j else 0,
                                scalar=0)
     return element
Пример #6
0
    def d2q2element(p: int, q: int, r: int, s: int, factor: Union[float, int])\
            -> DualBasisElement:
        """
        Build the dual basis element for symmetric form of 2-marginal

        :param p: tensor index
        :param q: tensor index
        :param r: tensor index
        :param s: tensor index
        :param factor: scaling coeff for a symmetric constraint
        :return: the dual basis of the mapping
        """
        dbe = DualBasisElement()
        dbe.add_element('cckk', (p, q, r, s), -1.0 * factor)
        dbe.add_element('kkcc', (r, s, p, q), +1.0 * factor)
        if q == s:
            dbe.add_element('ck', (p, r), factor)
        if p == r:
            dbe.add_element('ck', (q, s), factor)
        if q == r:
            dbe.add_element('ck', (p, s), -1. * factor)
        if p == s:
            dbe.add_element('ck', (q, r), -1. * factor)

        dbe.dual_scalar = (
            kronecker_delta(q, s) * kronecker_delta(p, r) -
            kronecker_delta(q, r) * kronecker_delta(p, s)) * factor
        return dbe
Пример #7
0
def tpdm_antisymmetry_constraint(dim: int) -> DualBasis:
    """
    The dual basis elements representing the antisymmetry constraints

    :param dim: spinless Fermion basis rank
    :return: the dual basis of antisymmetry_constraints
    :rtype: DualBasis
    """
    # dual_basis = DualBasis()
    dbe_list = []
    for p, q, r, s in product(range(dim), repeat=4):
        if p * dim + q <= r * dim + s:
            if p < q and r < s:
                tensor_elements = [
                    tuple(indices) for indices in _coord_generator(p, q, r, s)
                ]
                tensor_names = ['cckk'] * len(tensor_elements)
                tensor_coeffs = [0.5] * len(tensor_elements)
                dbe = DualBasisElement()
                for n, e, c in zip(tensor_names, tensor_elements,
                                   tensor_coeffs):
                    dbe.add_element(n, e, c)

                # dual_basis += dbe
                dbe_list.append(dbe)

    return DualBasis(elements=dbe_list)
Пример #8
0
def tpdm_to_opdm_mapping(dim: int, normalization: Union[float,
                                                        int]) -> DualBasis:
    """
    Construct the DualBasis for mapping of the tpdm to the opdm

    Args:
        dim: dimension of the spin-orbital basis.
        normalization: Scalar for mapping tpdm to opdm.  Generally, this is
                       1 / (N - 1) where N is the number of electrons.
    Returns:
        DualBasis for all dim^2
    """
    db_basis = DualBasis()
    for i in range(dim):
        for j in range(i, dim):
            dbe = DualBasisElement()
            # contract over tpdm terms
            for r in range(dim):
                # duplicate entries get summed in DualBasisElement
                dbe.add_element('cckk', (i, r, j, r), 0.5)
                dbe.add_element('cckk', (j, r, i, r), 0.5)

            # opdm terms
            dbe.add_element('ck', (i, j), -0.5 * normalization)
            dbe.add_element('ck', (j, i), -0.5 * normalization)
            dbe.simplify()
            db_basis += dbe

    return db_basis
Пример #9
0
def opdm_to_ohdm_mapping(dim: int) -> DualBasis:
    """
    Map the ck to kc

    D1 + Q1 = I

    Args:
        dim: dimension of the spin-orbital basis
    Returns:
        DualBasis for the 1-RDM representability constraint
    """
    dbe_list = []
    for i in range(dim):
        for j in range(i, dim):
            dbe = DualBasisElement()
            if i != j:
                dbe.add_element('ck', (i, j), 0.5)
                dbe.add_element('ck', (j, i), 0.5)
                dbe.add_element('kc', (j, i), 0.5)
                dbe.add_element('kc', (i, j), 0.5)
                dbe.dual_scalar = 0.0
            else:
                dbe.add_element('ck', (i, j), 1.0)
                dbe.add_element('kc', (i, j), 1.0)
                dbe.dual_scalar = 1.0

            # db += dbe
            dbe_list.append(dbe)

    return DualBasis(elements=dbe_list)  # db
Пример #10
0
def test_dbe_iterator():
    dbe = DualBasisElement(tensor_names=['A'] * 5,
                           tensor_coeffs=[1] * 5,
                           tensor_elements=[(i, i) for i in range(5)])
    for idx, (t, v, c) in enumerate(dbe):
        assert t == 'A'
        assert v == (idx, idx)
        assert c == 1
Пример #11
0
def test_simplify():
    i, j, k, l = 0, 1, 2, 3
    names = ['opdm'] * 3 + ['oqdm']
    elements = [(i, j), (i, j), (i, l), (l, k)]
    coeffs = [1, 1, 0.25, 0.3]
    dbe = DualBasisElement(tensor_names=names,
                           tensor_elements=elements,
                           tensor_coeffs=coeffs)
    dbe.simplify()
    assert len(dbe.primal_tensors_names) == 3
    assert set(dbe.primal_coeffs) == {2, 0.25, 0.3}
    assert set(dbe.primal_tensors_names) == {'opdm', 'oqdm'}
    assert set(dbe.primal_elements) == {(0, 1), (0, 3), (3, 2)}
Пример #12
0
def test_add_element():
    with pytest.raises(TypeError):
        dbe = DualBasisElement()
        dbe.add_element('cckk', [1, 2, 3, 4], 0.5)

    with pytest.raises(TypeError):
        dbe = DualBasisElement()
        dbe.add_element(5, (1, 2, 3, 4), 0.5)

    with pytest.raises(TypeError):
        dbe = DualBasisElement()
        dbe.add_element('a', (1, 2, 3, 4), 'a')

    dbe = DualBasisElement()
    dbe.add_element('cckk', (1, 2, 3, 4), 0.5)
    dbe.constant_bias = 0.33

    assert dbe.primal_coeffs == [0.5]
    assert dbe.primal_tensors_names == ['cckk']
    assert dbe.primal_elements == [(1, 2, 3, 4)]

    dbe.add_element('ck', (0, 1), 1)
    assert dbe.primal_coeffs == [0.5, 1]
    assert dbe.primal_tensors_names == ['cckk', 'ck']
    assert dbe.primal_elements == [(1, 2, 3, 4), (0, 1)]

    dbe2 = DualBasisElement()
    with pytest.raises(TypeError):
        dbe2.join_elements((1, 1))

    dbe2.constant_bias = 0.25
    dbe2.add_element('cckk', (1, 2, 3, 4), 0.5)
    dbe3 = dbe2.join_elements(dbe)
    assert np.isclose(dbe3.constant_bias, 0.58)

    assert set(dbe3.primal_elements) == {(0, 1), (1, 2, 3, 4)}
    assert np.allclose(dbe3.primal_coeffs, [1, 1])
    assert set(dbe3.primal_tensors_names) == {'ck', 'cckk'}
Пример #13
0
def test_add_dualelement():
    a = np.random.random((5, 5, 5, 5))
    b = np.random.random((4, 4, 4))
    c = np.random.random((3, 3))
    at = Tensor(tensor=a, name='a')
    bt = Tensor(tensor=b, name='b')
    ct = Tensor(tensor=c, name='c')
    mt = MultiTensor([at, bt, ct])
    assert isinstance(mt.dual_basis, DualBasis)

    dbe = DualBasisElement()
    dbe.add_element('a', (0, 1, 2, 3), 4)
    mt.add_dual_elements(dbe)
    assert len(mt.dual_basis) == 1
Пример #14
0
def nb_constraint(dim, nb):
    """
    Constraint the trace of the alpha block of the opdm to equal the number
    of spin-down electrons

    Args:
        dim: Dimension of the spin-orbital basis.
        na: Number of spin down electrons

    Returns:
        DualBasis representing the cosntraint that is length 1
    """
    dbe = DualBasisElement()
    for i in range(dim // 2):
        dbe.add_element('ck', (2 * i + 1, 2 * i + 1), 1.0)
    dbe.dual_scalar = nb
    return DualBasis(elements=[dbe])
Пример #15
0
def sz_constraint(dim: int, sz: Union[float, int]) -> DualBasis:
    """
    Constraint on the 1-RDM

    Args:
        dim: dimension of the spin-orbital basis.
        sz: expectation value of the magnetic quantum number.

    Returns:
        DualBasis
    """
    dbe = DualBasisElement()
    for i in range(dim // 2):
        dbe.add_element('ck', (2 * i, 2 * i), 0.5)
        dbe.add_element('ck', (2 * i + 1, 2 * i + 1), -0.5)
    dbe.dual_scalar = sz
    return DualBasis(elements=[dbe])
Пример #16
0
def na_constraint(dim: int, na: Union[float, int]) -> DualBasis:
    """
    Constraint the trace of the alpha block of the opdm to equal the number
    of spin-up electrons

    Args:
        dim: Dimension of the spin-orbital basis.
        na: Number of spin up electrons

    Returns:
        DualBasis representing the cosntraint that is length 1
    """

    dbe = DualBasisElement()
    for i in range(dim // 2):
        dbe.add_element('ck', (2 * i, 2 * i), 1.0)
    dbe.dual_scalar = na
    return DualBasis(elements=[dbe])
Пример #17
0
def test_synthesis_dualbasis():
    a = np.random.random((5, 5))
    b = np.random.random((4, 4))
    c = np.random.random((3, 3))
    at = Tensor(tensor=a, name='a')
    bt = Tensor(tensor=b, name='b')
    ct = Tensor(tensor=c, name='c')
    dbe = DualBasisElement()
    dbe.add_element('a', (0, 1), 4)
    dbe.add_element('a', (1, 0), 4)
    mt = MultiTensor([at, bt, ct], DualBasis(elements=[dbe]))

    A, c, b = mt.synthesize_dual_basis()
    assert isinstance(A, sp.sparse.csr_matrix)
    assert isinstance(c, sp.sparse.csr_matrix)
    assert isinstance(b, sp.sparse.csr_matrix)
    assert A.shape == (1, 50)
    assert b.shape == (1, 1)
    assert c.shape == (1, 1)
Пример #18
0
def tpdm_trace_constraint(dim: int, normalization: float) -> DualBasisElement:
    """
    Generate the trace constraint on the 2-PDM

    Args:
        dim:  Dimension of the spin-orbital single-particle Hilbert space
        normalization: Desired trace value.

    Returns: A DualBasisElement (Row of the constraint matrix) encoding
             the trace constraint on the 2-RDM.
    """
    tensor_elements = [(i, j, i, j) for i, j in product(range(dim), repeat=2)]
    tensor_names = ['cckk'] * (dim**2)
    tensor_coeffs = [1.0] * (dim**2)
    bias = 0
    return DualBasisElement(tensor_names=tensor_names,
                            tensor_elements=tensor_elements,
                            tensor_coeffs=tensor_coeffs,
                            bias=bias,
                            scalar=normalization)
Пример #19
0
    def g2d2map(p: int,
                q: int,
                r: int,
                s: int,
                factor: Optional[Union[float, int]] = 1) -> DualBasisElement:
        """
        Build the dual basis element for a symmetric 2-marginal

        :param p: tensor index
        :param q: tensor index
        :param r: tensor index
        :param s: tensor index
        :param factor: weighting of the element
        :return: the dual basis element
        """
        dbe = DualBasisElement()
        if q == s:
            dbe.add_element('ck', (p, r), -1. * factor)
        dbe.add_element('ckck', (p, s, r, q), 1.0 * factor)
        dbe.add_element('cckk', (p, q, r, s), 1.0 * factor)
        dbe.dual_scalar = 0

        return dbe
Пример #20
0
def test_synthesis_element():
    a = np.random.random((5, 5))
    b = np.random.random((4, 4))
    c = np.random.random((3, 3))
    at = Tensor(tensor=a, name='a')
    bt = Tensor(tensor=b, name='b')
    ct = Tensor(tensor=c, name='c')
    mt = MultiTensor([at, bt, ct])

    dbe = DualBasisElement()
    dbe.add_element('a', (0, 1), 4)
    dbe.add_element('a', (1, 0), 4)
    with pytest.raises(TypeError):
        dbe.add_element(5)

    with pytest.raises(TypeError):
        mt.add_dual_elements(5)

    mt.add_dual_elements(dbe)
    colidx, data_vals = mt.synthesize_element(dbe)
    assert data_vals == [4, 4]
    assert colidx == [1, 5]
    assert [at.data[0, 1], at.data[1, 0]] == [at(0, 1), at(1, 0)]
Пример #21
0
def test_dbe_string():
    dbe = DualBasisElement(tensor_names=['A'] * 5,
                           tensor_coeffs=[1] * 5,
                           tensor_elements=[(i, i) for i in range(5)])

    assert dbe.id() == "A(0,0)	A(1,1)	A(2,2)	A(3,3)	A(4,4)\t"